7.10. Improving Object Identification

7.10.1. Matching Objects with Changeable Texts
7.10.2. Exact Matching with =
7.10.3. Wildcard Matching with ?=
7.10.4. Regular Expression (regex) Matching with ~=
7.10.5. Real (Multi-Property) Name Properties

When Squish records tests it uses object properties to uniquely identify each object. For each object that Squish identifies it creates an entry in the Object Map. Each entry is essentially a pair of names—a symbolic name (a unique string starting with a colon), and a real (multi-property) name (a braces enclosed space-separated list of property name–value pairs). When tests are run Squish reads the names in the test script as it encounters them and tries to match them to the corresponding application objects.

For properties that have normal values the matching is done on the string value. For properties that have object values (i.e., the value is the real name of another object), the matching is done using Squish's normal object lookup functionality.

Some properties can only be matched using exact matching, while others can use exact, wildcard, or regex matching. Those properties that can only use exact matching are the type property (on Squish for Web this is the tagName property), the basename property (on Squish for Java™), and any other properties whose values are object values (i.e., the names of other objects), e.g., the container and window properties. Note that in Squish for Web the className property is unusual in that its value is a list of strings (class names) and if we use exact matching the match will work if any of the element's class attribute's classes matches the one we have specified.

[Tip]Java-specific

Since wildcard and regex matching are not supported for the type and basename properties it can be difficult to have identical test scripts that run on both Windows and Linux if there are Windows- and Linux-specific classes involved. The solution is to use the basename property and set it to the common base class that the platform-specific classes derive from. (This isn't an issue with other toolkits because even cross-platform ones like Qt use the same class names on all platforms.)

Starting with Squish 3.2, the syntax of multiple property (real) names has been enhanced to allow for more flexible matching of property values.

7.10.1. Matching Objects with Changeable Texts

One commonly encountered problem is that many applications change the texts used by some widgets. For instance, a button's text might change from Pause to Resume and back again, or the application might put the name of the current file or workspace in the main window's title bar caption. For example, lets assume that we have the following real name for a fictional MainWindow object in our application with the caption “UsefulApp v1.3 - July Sales.dat”:

{caption='UsefulApp v1.3 - July Sales.dat' type='MainWindow'}

This multiple property name will match the first object in the application which is of type MainWindow and whose caption matches the one shown above.

Such names work perfectly well in most situations and they are generated automatically when recording a test (see Object Name Generation (Section 7.12) for more information on that topic). Unfortunately, since the caption's text is variable it is vulnerable to changes—for example, if we start testing the 1.4 version of the application or if we want to switch to testing a different data file. In either of these cases the caption text will change, and any existing tests that rely on it will now fail.

By default, Squish uses exact matching for property values using the = (equality) operator. However, Squish also provides two other matching operators, ?= (wildcard) and ~= (regular expression, or “regex”).

If we wanted to make the MainWindow's real name more robust we could use the wildcard or the regex operator. Here is an example using the wildcard operator:

{caption?='UsefulApp*' type='MainWindow'}

We'll formally describe the wildcard syntax in a moment, but for now we will just explain what the example means. This says that the 'caption' property's text must begin with “UsefulApp” followed zero or more other characters. (A * stands for zero or more of any characters—so here we expect it to match, “ v1.3 - July Sales.dat” or “ v1.4 - August Sales.dat” or similar. Clearly this is a lot more robust than using the = (equality) operator, although we do have to learn a few symbols (actually, just ?, *, \, [ and ]) to take advantage of this facility.

We could of course achieve the same thing using the regex operator, for example:

{caption~='UsefulApp.*' type='MainWindow'}

This regex match has exactly the same meaning as the wildcard match described above, although in general the regex syntax is much more complicated—and also more versatile—than the wildcard syntax.

7.10.2. Exact Matching with =

The = (equality) operator is used for exact matches. This kind of matching can be used in all situations, and is the only kind of matching that is allowed for the type property and for properties whose value is an object (i.e., is specified using a real name). Here is an example:

{type='LineEdit' visible='1' buddy={type='Label' text='Forename:'}}

This real name is used to identify an object of type LineEdit that has a 'visible' property set to true (1) and that has an associated label—a 'buddy'—which in turn is specified using a real name.

7.10.3. Wildcard Matching with ?=

The ?= (wildcard) operator is used for inexact matches. This kind of matching cannot be used for the type property or for symbolic object names.

When wildcard matching is in use the ?, *, [, ], and \ characters all take on special meanings and are not matched literally. All other characters are matched literally.

Table 7.2. The Wildcard Special Characters

?This character stands for any one single character no matter what it is
*This character stands for any number of any characters—including no characters at all
?*These two characters together stand for at least one of any character (i.e., any one single character followed by zero or more of any character)
[...]Brackets are used to specify a set of one or more characters any one of which must be matched. For example, [0-9] matches exactly one digit, and [aAbBcC] matches only an "a", "b", or "c", whether upper- or lower-case
\The backslash is used to escape one of the special characters, so \? stands for a literal "?", and \* stands for a literal "*". Unfortunately, brackets cannot be escaped so always have their special meaning, so the only way to match literal brackets is to use ? (which will match anything), or to use regex syntax


Here is an example:

{type='LineEdit' visible='1' buddy={type='Label' text?='Name*\?'}}

This real name is used to identify an object of type LineEdit that has a 'visible' property set to true (1) and that has an associated label—a 'buddy'—which in turn is specified using a real name. But here the buddy's name is specified using wildcard matching and must contain the text “Name” followed by zero or more other characters followed by a literal?”.

Here's a second example:

{caption?='UsefulApp v[1-9].[0-9] - ?*.[dD][aA][tT]' type='MainWindow'}

Here, the 'caption' property must have a value that starts with the literal text “UsefulApp v” followed by a digit (but not including zero), then a period, then another digit, then a space, a hyphen, and a space, and then at least one character (indicated by the ?), then zero or more other characters (due to the *), followed by “.dat” (in upper- or lower-case). Notice that if we had specified the filename part of the caption as *.[dD][aA][tT] it would have matched the suffix alone, i.e., “.dat” since the * symbol can match zero characters. By starting with the ? we ensure that at least once character is matched in front of the suffix.

7.10.4. Regular Expression (regex) Matching with ~=

The ~= (regex) operator is used for inexact matches. This kind of matching cannot be used for the type property or for properties whose value is an object (i.e., is specified using a real name). Regex matching allows us to write more sophisticated—and potentially harder to understand and maintain—matching expressions than can be achieved using wildcard matching. In fact we recommend using wildcard matching where possible simply because it is easier, both to read and write.

For Squish for Web editions the regex syntax is the same as the one supported by JavaScript. Documentation for this syntax is available from Regular-Expressions.info and w3schools.com. For all other Squish editions the Qt QRegExp syntax is used—this is documented here: QRegExp.

7.10.5. Real (Multi-Property) Name Properties

Which properties does a particular object have that can be used for identifying an object? The answer is not straightforward because the properties are discovered dynamically.

To take the Qt toolkit as a typical example: Squish exposes all the object's base class's properties (i.e., QObject's properties), also any object-type-specific properties that have been added by the supplier or by the AUT (e.g., through subclassing), and finally some artificial properties that are especially useful to Squish.

In general, all of an object's properties are potentially usable for identifying it (e.g., using them in a real name in calls to the findObject and waitForObject functions). However, only the non-artificial properties are suitable for use in verifications (e.g., in calls to the test.compare function and other test module functions).

To find out what an object's non-artificial properties are, either look up the object's type in its toolkit's documentation or use the Spy. To use the Spy begin by launching the AUT (see the Launch AUT action (Section 8.1.1.22)), then interact with the AUT until the relevant AUT object is visible. At this point context switch back to the Squish IDE and invoke the pick action (see the Application Objects view (Section 8.2.1)); and pick the object of interest. Now all the object's non-artificial properties will be shown in the Properties view (Section 8.2.11). To find out the object's artificial properties, invoke the context menu on the object in the Application Objects view (Section 8.2.1) and copy its real name to the clipboard: any properties in the real name that are not listed in the Properties view (Section 8.2.11) are artificial properties.

Table 7.3. Squish's Key Artificial Properties

Property NameToolkitsNotes
aboveLabelMac OS X, iPhoneThe symbolic name of the label above the object being identified
aboveObjectWindowsThe symbolic name of the object above the object being identified
aboveWidgetQtThe symbolic name of the widget above the object being identified
aboveWidgetTextQtThe text held by the widget above the object being identified
aboveWidgetTypeQtThe type of the widget above the object being identified
basetypeJavaA more versatile alternative to type for Java toolkits
buddyQtThe symbolic name of the label associated with the object being identified
buddyNameQtThe objectName of the label associated with the object being identified
buddyTextQtThe text of the label associated with the object being identified
columnQtThe object being identified's column (if it is inside a multi-valued object such as a table or tree)
columnNumberMac OS XThe object being identified's column (if it is inside a multi-valued object such as a table or tree)
containerQt, Mac OS X, iPhone, WindowsThe symbolic name of the object that contains the object being identified
containerLabelQtThe text label of the object that contains the object being identified
containerNameQtThe name (e.g., caption) of the object that contains the object being identified
containerTypeQtThe type of the object that contains the object being identified
documentViewMac OS XUsed for scrollbars (NSScroller): the symbolic name of the document view which the object being identified belongs to (i.e. the view it scrolls)
isApplicationMenuItemMac OS XUsed for menu items (NSMenuItem): if this property is 1, then the menu item is the menu item in the menu bar that opens the application menu. For all other menu items, this property is 0.
leftLabelMac OS X, iPhoneThe symbolic name of the label left of the object being identified
leftObjectWindowsThe symbolic name of the object to the left of the object being identified
leftWidgetQtThe symbolic name of the widget to the left of the object being identified
leftWidgetTextQtThe text held by the widget to the left of the object being identified
leftWidgetTypeQtThe type of the widget to the left of the object being identified
nameQtThe object being identified's objectName
occurrenceQt, Mac OS X, iPhone, WindowsA number that uniquely identifies an object which would otherwise be identical to another object (due to having exactly the same property values)
parentItemMac OS XThe symbolic name of the object being identified's parent object
rightLabelMac OS X, iPhoneThe symbolic name of the label right of the object being identified
rowQtThe object being identified's row (if it is inside a multi-valued object such as a list, table, or tree)
rowNumberMac OS XThe object being identified's row (if it is inside a multi-valued object such as a list, table, or tree)
tableViewMac OS XThe symbolic name of the NSTableView in which the object being identified belongs
typeAllThe name of the object being identified's type (or class). For most GUI toolkits this must always be present in a real (multi-property) name; however, it is not required for Squish for Windows or Squish for Web.
unnamedQtIf the object being identified does not have an objectName this property's value is "1"; otherwise its value is "0"
visibleQt, Mac OS X, iPhone, WindowsIf the object being identified is logically visible (i.e., not completely obscured by one or more other AUT objects), this property's value is "1"; otherwise its value is "0". In tests for native Windows applications, this property assumes the values true and false.
windowQt, Mac OS X, iPhoneThe symbolic name of the window that contains the object being identified
windowNameQtThe name (caption) of the window that contains the object being identified
windowOccurrenceQtThe occurrence number of the window that contains the object being identified
windowTypeQtThe type of the window that contains the object being identified