27
How to achieve robust component recognition

The most important feature of a GUI test-tool is the recognition of the graphical components. QF-Test offers a lot of configuration capabilities in that area. This chapter gives an overview over the most common strategies and settings to make the component recognition as stable as possible in a project.

We also recommend to take a closer look at section 30.12 and section 36.2.

Note You have to figure out the component recognition strategy before you start utilizing QF-Test for a large testing area in your project. Otherwise you can get into serious troubles in maintaining your tests. Some hints for doing that are described in chapter 24.

27.1
Using the default configuration

In most of the projects the default configuration works very well. The default configuration takes the name of a component, its class (type) and also its hierarchy (structure of window) into account for recognizing a component.

You will get troubles using this configuration, if

If the developers do not use any names, QF-Test uses other properties, like the label, the text of a button or the geometry for the recognition of a component. In this case the default configuration can also work if those labels, the component structure and the geometry stay stable. In this case your tests should make sure that the windows of the SUT are always opened with or resized to the same size.

The default configuration for recording components looks like this:

Figure 27.1:  Default configuration for component recording

The default configuration for recognizing a component during playback looks like this:

Figure 27.2:  Default configuration for component recognition
27.2
Using the 'Name overrides everything' mode

If your developers use stable and unique names for all important components which can be accessed by a test, e.g. buttons, tables or text-fields, you can consider changing the configuration to the 'Name overrides everything' mode. This has the advantage that only names of those components and the window they belong to will be used for recognizing the component. Changes to the SUT's component hierarchy will the have no effect on the recognition of those components based on their unique name.

This setting will cause trouble if:

The 'Name overrides everything' configuration for component recording looks like this:

Figure 27.3:  'Name overrides everything' configuration for component recording

The 'Name overrides everything' configuration for recognizing a component during playback looks like this:

Figure 27.4:  'Name overrides everything' configuration for component recognition
27.3
Using regular expressions for working with dynamic window titles

In a lot of applications you will face the situation that the developers do not use unique names and QF-Test keeps recording the same components again and again in different places. Playback with previously recorded components may still works unless the window geometry changes significantly.

In this case it is very likely that the title of the main window changes frequently, e.g. to display a version string, a user name, a file name or some other variable information. If you want to keep your tests working and prevent recording multiple variants of this window and all its components, you have to select the respective 'Window' node in the and edit its 'Feature' attribute to replace the dynamic parts of that title with a regular expression. Be sure to check the 'Use regexp' box. Now your tests should work again.

Here you see the use of a regular expression for a component of the JCarConfigurator. Its 'Feature' attribute has to start with 'Edit' followed by an optional dynamic part:

Figure 27.5:  Using a regular expression in the 'Feature' attribute

QF-Test uses regular expressions at many places. You can find detailed information at section 36.4 to learn more about how to use them.

Note QF-Test assigns the 'Id' of a component automatically and may use the 'Feature' attribute to generate it like described in section 6.3. The 'Id' attribute is an artificial concept for QF-Test's internal use to map actions onto recorded components. Thus it can be pleasing to change it for better readability afterwards. When changing the 'Id' QF-Test provides the opportunity to adapt all references automatically.

27.4
Influencing the names by implementing a NameResolver

In GUI testing projects you can face a lot of interesting naming concepts. Sometimes the components in an application have no names, but the testers know an algorithm how to name them reliably. Sometimes existing names change from time to time or are completely dynamic, e.g. you can get a name 'button1' after the first recording and after the second recording you get 'button2'. Another situation could be that the current version of the application is part of the name of a dialog window.

In such cases you should take a closer look at the NameResolver interface of QF-Test.

A NameResolver can be used to change or remove names set by developers for the QF-Test perspective. They are only removed for QF-Test not from the real source code.

You can think about utilizing NameResolvers in following cases:

If you can achieve per-window uniqueness of names with the help of a NameResolver you can also think about switching to the 'Name overrides everything' setting described in section section 27.2.

Note Whenever possible it is preferable that developers set the names directly in their source code as they best know the context of that component. Implementing a NameResolver can become an excruciating task if the developers change the content of the GUI a lot.

NameResolvers are well described in section 39.1.

27.5
Handling class changes due to re-factoring by using 'Record system-classes only'

You can configure QF-Test to record the system base classes of components instead of custom class names.System classes are javax.swing... and java.awt... classes for Java/Swing and org.eclipse.swt.widgets... classes for Java/SWT applications.

Figure 27.6:  Option to configure recording of system classes only

If you set this option, you will be safe against re-factoring steps of the developers who may change the class structure or rename classes. This option will also protect you from obfuscators which change the name of classes.

In most cases you can work with this option as it could always happen that a class name changes and it is definitely better to be on the safe side instead of having problems, which could be solved easily.

However, you should not work with this option if the classes are important for the recognition of components, i.e. if development did not assign useful names but implemented different custom classes for specific containers that QF-Test can use to partition the set of components of the SUT.

3.1+ A mixed approach is also possible by implementing a ClassNameResolver. This can be useful you only want to get system classes for some components, but not all, e.g. when using a third-party library. Please see subsection 39.1.2 for more details.

27.6
Avoiding recording every component or using generic components

By now you know how to optimize the component recognition for your needs, but you still have to record every component before you can use it in your tests.

As you can imagine, it can be tiring to record each and every component required for a test. Sometimes this may even become impossible, e.g. when you have changing identifiers or changing labels. A typical situation could be localization testing of an application.

Another situation could be the usage of a GUI framework of your developers. You could have a lot of very similar dialogs, where only some components are different. But you still have to record all parts, which are actually the same, like navigation buttons.

QF-Test offers a feature to reduce the recording of components to a minimum. This concept is called 'Generalizing components'. It consists of making use of variables in the component's details or simply to remove dynamic parts of it.

The general approach for generalizing components is as follows:

  1. Record some components that you want to generalize and compare them.
  2. Create one generic component with an ID, which contains 'generic' so that you can recognize it later.
  3. Remove all attributes that you do not want to use in the recognition in that generic component.
  4. Determine the main properties that you want to use for recognition, e.g. 'Name', 'Feature' or 'Class index'.
  5. Set a variable for the respective attribute, e.g. $(name).
  6. To prevent false positive matches, disable recognition based on geometry by specifying '-' for the 'X' and 'Y' attributes.
  7. Specify '@generic' in the 'Comment' attribute for the generic component to prevent it from inadvertently being removed by the 'Remove unused components' action.
  8. Create a procedure accessing the generic component and use the variable(s) from the previous step as parameter(s).

Note Generic components are very handy for replaying tests, but QF-Test will not use them for recording. You will always get the real component recorded in the test-suite, but can then change the created sequence to make use of the respective generic component.

3.1+27.7
Switching component recognition settings dynamically

Since QF-Test version 3.1 it is even possible to change component recognition options dynamically. Thus you are very flexible and you can combine different settings for your SUT.

Setting options at runtime can be done via a 'Server script' or 'SUT script' - depending on the option - and calling rc.setOption(OPTION_NAME, OPTION_VALUE). All possible options can be found in section 29.2 for recording and in section 29.3 for replaying tests.