A stable method to address GUI controls is crucial for a maintainable test project. But how does Squish go about generating object names? What makes a good object name? How can you identify poor object names? How can you configure Squish to generate (or reuse) better names? We will address these and other important questions arising in every professional GUI testing project.
Squish uses so-called Multi-Property Object Names to reference elements of the user interface. Instead of recording clicks at certain pixel coordinates on the screen, Squish chooses a small set of properties which identifies a control. Each such set forms an object name. However, there is no single set of properties which is appropriate for all objects and all applications. Luckily, Squish supports very powerful configuration facilities for adjusting the set of properties considered when generating object names.
The Challenges Of Naming Things
In general, multi-property object names are great and provide a number of important benefits, most importantly by allowing the creation of object references that are independent of
- The screen resolution or operating system.
- The position of the referenced control on the screen
- Implementation details of the UI, such as the position of the control in the object hierarchy.
All of these greatly help with making tests more robust, even when the application under test changes or when the tests are executed on a different operating system. However, leveraging this potential is not trivial, which poses a risk of creating fragile object names. The difficulty arises from two central questions regarding the design of object names:
- Which properties should be considered when generating an object name? Clearly, including e.g. the X position and the width of a control in the object name would help with uniquely identifying an object. However, it would make the object name work only for very specific resolutions and font sizes. Hence, these are typically not useful for object identification.
- How many properties should be included when generating an object name? The more properties used for an object name, the more fragile it becomes. A change in a value for any of the used properties will automatically cause the object name to fail finding the object. On the other hand, using too few properties for an object name increases the likelihood of names being ambiguous. An object name purely identifying UI controls by e.g. their type and their text may end up matching more than one control (consider e.g. two buttons with the text ‘OK’).
Do I Need To Worry?
Just like the test script code, the object map is also subject to maintenance work. It’s highly advisable to review the set of object names used by test scripts every now and then to see whether there are any indicators of poor object naming:
- Occurrence values. The ‘occurrence’ property is added to object names in case Squish finds no other way to make an object name unambiguous such that it references exactly one object. This is such a common problem that there is a dedicated article in the Knowledge Base about it. Also, the Squish IDE hints at this issue by showing warning icons next to those object names requiring the use of the ‘occurrence’ property. The takeaway here is that it’s an indication of having too few or the wrong properties in the object name.
- Multiple, very similar names, differing in just one property. Many user interface controls change properties as the application is being executed. In particular, properties used for object identification can change. One example for this is the caption of a window: the text commonly shows information such as version numbers or file paths. Opening a different file will change the caption of the window. Thus, the previously generated name is no longer applicable, causing a new name to be generated. Eventually, you end up with a lot of very similar names identifying the same controls.
How Object Names Are Generated
The two main use cases as part of which Squish generates object names are:
- When recording script code.
- When right-clicking an object in the ‘Application Objects’ tree and selecting ‘Copy Real Name’, ‘Copy Symbolic Name’ or ‘Add to Object Map’ in the context menu.
However, Squish will not always generate new object names. Doing so would make the Object Map grow in size very quickly, making maintenance more demanding. Instead, Squish will first check whether any name stored in the object map can be reused. Every time the name of an object is needed, Squish will consider all entries in the object map and try to find the first name (if any) which matches the object at hand. Only if none of the existing names match, a new name is generated from scratch.
Making Object Names Reusable
Ideally, no object names need to be generated. Instead, Squish is able to reuse an existing name. To increase the chances of Squish being able to reuse an object name, existing names need to be made reusable. Ideally, this happens very early during the testing project. Two main approaches are available for this:
- Using wildcard matches. By default, Squish will perform a basic text comparison between the property value specified in the object name and the actual property value. However, it is possible to augment this using wildcards (also known as “filename globbing”). For example, does a portion of text in the title bar of your application change regularly? No problem! Change the ‘text’ property value of the title bar object to either search for the constant portion of the text, followed by a wildcard, or search the entire text of the title bar using a regular expression matching the dynamic portions of the text. See the Knowledge Base article Adjust object names for objects with changeable texts for more on this.
- Removing unneeded properties. A more extreme approach than using wildcard matches, object names can be made more general (less specific) by removing properties, For example, multiple object names for a button might differ in just their user visible text since the button changes its caption at runtime. It is possible that the button text is not even required to identify the object uniquely, perhaps because another property (such as objectName) is also used. In this case, simply removing the text property from the object name would be a good improvement.
Configuring Name Generation
If it turns out that a new object name needs to be generated, Squish will choose a set of properties depending on the specific object at hand. The exact set of properties which comprises an object name is freely configurable using so-called Descriptor Files. Each file contains multiple ‘descriptors’ which describe the set of properties to consider when building object names for different types of objects. You can edit these XML files with any text editor.
There are two copies of each descriptor file:
- The default configuration is stored in
<SQUISHDIR>/etc/<WRAPPER>_descriptors.xmlwhere SQUISHDIR stands for the Squish installation directory and ‘wrapper’ is the name of the UI technology used for the application under test, e.g. ‘qt’ or ‘mac’. This file serves as an example of how to define custom descriptors.
- User-specific customizations should be stored in
<SQUISH_USER_SETTINGS>/<wrapper>_user_descriptors.xmlwhere SQUISH_USER_SETTINGS stands for the user-specific Squish configuration directory. This is typically a directory called ‘.squish’ (note the leading dot!) in the home directory of the user.
In general, it is preferable to edit the user-specific descriptor file. Any descriptor in the user-specific descriptor file will override the defaults, and the customizations won’t be lost when upgrading Squish.
Each file consists of multiple ‘descriptor’ elements. A descriptor defines a set of conditions which decides if the descriptor is applicable to some given object as well as the properties to use for generating an object name. Here’s a simple example:
<objectdescriptors> <descriptor> <type name="Button"/> <realidentifiers> <property>text</property> </realidentifiers> </descriptor> </objectdescriptors>
This descriptor defines that the text property should be used when generating names for objects which are of type Button. But what if the GUI tests should also work on applications using a different translation, e.g. French? Clearly, using the user-visible text for object identification would not be a good idea in this case.
Hence, you can add a descriptor like this to the user-specific descriptor file to override the default descriptor by specifying that an internal ‘id’ exposed by the Button object (provided that such a property exists) is used, and the ‘text’ property is ignored:
<objectdescriptors> <descriptor> <type name="Button"/> <realidentifiers> <property>id</property> <property exclude="yes">text</property> </realidentifiers> </descriptor> </objectdescriptors>
This is just a simple example to whet your appetite – the Squish manual contains a much more comprehensive discussion of the Descriptor File Format which you are very much encouraged to have a look at!
Object names are important, and not easy to get right. The sooner you start working on them, the better! Make sure to:
- Decide on which properties to use for identifying objects. Properties which are stable across your planned test execution setups are preferred.
- Review existing object names — are there opportunities for reuse? Any signs of occurrence properties?
- Configure Squish to suit your needs: use wildcards in object names to make them reusable, configure descriptor files as needed to include just your desired properties in object names.