Motivation

Squish supports automating QtQuick 2.x based applications out of the box. One frequently asked question is about custom QML components or custom QtQuick controls and how Squish supports these.

Testing QtQuick with Squish is very similar to Web testing in this regard. By default, Squish will record on the basic elements that a component is made of. For custom controls this means that Squish will usually record on some BackgroundImage, Text or Rectangle item instead of the expected control.

By extending Squish and giving it knowledge of these custom types, we can record test scripts that are easier to understand and maintain.

A custom button example

Take for example the following small QtQuick application that shows two custom buttons.

The example can be started by passing the main QML file to the qml application which ships with Qt 5.

Testing the example in Squish

Picking on the example application with Squish will either yield the Rectangle or the Text item but never the parent FrogButton item. This is because both items fill the complete visual area of their parent FrogButton item.

Picking a custom button

Additionally, the object name for the Rectangle item inside those buttons is rather generic. Rectangles simply don’t have any good properties to identify them uniquely. The name will contain an occurrence value as soon as more than one FrogButton is being displayed at the same time. For the example application, the Rectangle in the second button will have a name of {container=':_QQuickWindow' id='buttonRect' occurrence='2' type='Rectangle' unnamed='1' visible='true'}.

However there’s a solution. Almost all behavior of QtQuick supported in Squish can be configured via Squish QML Extensions. These extensions are essentially normal QML files, and they allow customization of picking and recording behavior, as well as name generation in Squish.

Writing a Squish QML Extension

To write a Squish QML Extension, we will start with a QML file that creates a single SquishHook object, and which contains an isIgnored() function.

The priority: value here was chosen to be higher than the standard extensions that ship with Squish. This means that this extension will always be asked first about what to do with a QtQuick item.

The first check inside the isIgnored() function tests if the current item is a FrogButton. The check is needed to override the default behavior of filtering out objects if they are of type Item. The default rule comes from the fact that such an item does not have any kind of visual representation (it’s essentially invisible) and thus Squish ignores it.

The second check tests the type of the immediate parent item. In our example, this means that if isIgnored() is called for either the Rectangle or Text items inside the FrogButton then they will be ignored.

The final return at the end instructs Squish to ask another extension for the item in question since this extension should only customize the behavior for a FrogButton and its children.

Both checks together provide the desired behavior of always picking and recording on FrogButton instead of any of its child items.

After putting the above extension into lib/extensions/qtquick/ inside a Squish installation, picking will look slightly different:

Picking with Extension

Customizing object names in Squish QML Extensions

Now that picking works there’s still one task left, the object name for the button is still not quite perfect: {container=':_QQuickWindow' type='FrogButton' unnamed='1' visible='true'}

As soon as two FrogButtons are present in the same container they will get identical names, which will then result in an occurrence= value added to the object name. One way to improve this is to add the button’s text to the object name, assuming that buttons do not change their text after creation. This can be achieved from within a Squish QML Extension by adding another function to the extension file:

This is very similar to the checks done in isIgnored(). In this case the function has to return a list of Qt property names that should be included in the object name generated by Squish. For FrogButton it will add the text property only.

After adding this function to the extension, the new object name when picking the button will change to {container=':_QQuickWindow' text='First' type='FrogButton' unnamed='1' visible='true'}. Both buttons in the example will now have unique object names.

Wrapping it up

QtQuick is a very customizable UI technology and as such Squish also allows customizing how objects and names are handled when recording on a QtQuick based application. The shown example is of course very simple, but much more complex controls can be supported in the same way.

The complete example code as well as the Squish QML Extension and an example Squish testsuite is available for download.

When writing custom Squish QML Extensions it usually helps to use the QML console.log() to see when and for which item the extension is called. For example one could simple put the following at the start of the isIgnored function:
console.log(“isIgnored: ” + item);
That way one can see if the item in question ever reaches the extension.

From the explanation, the hierarchy rather sounds like a type-inheritance hierarchy than a hierarchy of QtQuick Items. In case of unknown/missing types and for more complex cases than the simple button example it’s probably better to ask this via our customer support. Writing Squish QML Extensions always needs a bit of knowledge about the application and its qml code and pasting (even parts of) the code is probably not a good idea.

Unfortunately, it only works if my object has a custom property. I had to add a custom property that my page didn’t need to get it to work. Is there a way to make it work without adding this custom property?

Also, I am unable to see my log in under Runner/Server Log, however, I do see my extension being loaded. Is there a place in the Squish GUI I can see this?

froglogic is a privately owned company which has been founded in 2003 and is known for its automated testing suite Squish with its flagship product Squish GUI Tester, the market-leading automated testing tool for GUI applications.