Skip to main content

Eliminating ambiguous cases in the recognition of test objects

Gu Yi He (heguyi@cn.ibm.com), Software Engineer, IBM Corporation
He Gu Yi
He Gu Yi is a software engineer from the IBM China Development Lab in Shanghai, China. He works on federated integration test projects, and his expertise includes enterprise content management, service-oriented architecture, and test automation.

Summary:  IBM® Rational® Functional Tester provides a test object recognition framework and a simple user interface for the tester to implement GUI-based test scripts. However, under some circumstances, such as testing an Eclipse-based application, you might find that the tested GUI is full of ambiguous test objects. These objects have almost the same properties, with only minor differences. It is hard to directly specify the pattern of the target object attributes and recognize the object. The recognition result might contain more than one analogical object, which leads to a recognition failure. This article shows you how to eliminate such ambiguous cases and gives you several guidelines to implement flexible and easy maintenance test scripts.

Date:  20 Mar 2009
Level:  Intermediate PDF:  A4 and Letter (483KB | 16 pages)Get Adobe® Reader®
Activity:  612 views

Prerequisites

Installation of IBM® Rational® Functional Tester, Version 7


An overview of Rational Functional Tester project structure

  1. Import the sample Rational Functional Tester project (see Download). You will see a script named BaseCase and a folder named util.
  2. Switch to the Java™ perspective by selecting Window > Open Perspective > Java. You will see the following three packages:
    • (default package)
    • resources
    • util

The BaseCase script is in the default package, and its helper class, BaseCaseHelper, plus the other configuration files associated with the script are in the Resources package. These two packages are invisible under the Functional Test perspective. You create the util package, along with classes in it. In the following sections, you will use this framework (see Figure 1).


Figure 1. The structure of a Rational Functional Tester project
package under Java Perspective


A quick glance at the find() method

You might be advised to use the find() method to get a test object when the getMappedTestObject() method does not work. The code in Listing 1 shows the signature of the find() method.


Listing 1. Find method signature

// Finds all candidates that match given search criteria starting at this TestObject
public TestObject[] find(Subitem properties);



The find() method works by comparing certain properties of the test objects with the given criteria to find a set of candidates. You can search a test object by a name/value pair that represents its property or contains one or more properties that will be matched against the children of the starting test object. If the recognition of a test object fails with the default getMappedTestObject() method, you can locate its ancestor first, then find the target test object by calling find() on the ancestor. Obviously, the find() method offers considerable benefit. The script is no longer dependent on the object map. The result of searching a candidate test object is predictable, thus robust. You can find a test object by its property values, which may be simple text. And it's easy to maintain the script.

However, the find() method cannot cover all of the cases when the method getMappedTestObject() does not work. There is not always an obvious set of property values to be matched. The find() method relies on a distinct set of property values. Therefore, if the test object does not have such a set of properties, the method will not function correctly. Although we can try the test objects one by one in the return array to find the correct one, that is not a smart way. And sometimes, it is difficult to find a recognizable ancestor of the test object, so the search has to begin from the top-level object, such as a window. This will reduce the recognition of the test object.


Navigation path-based object recognition

Considering the drawbacks of the find() and getMappedTestObject() methods, you need another way to solve the ambiguous cases in Rational Functional Tester object recognition. In this article, we introduce a navigation path-based method to find the target test object. We'll use the application ClassicsJavaA as an example. To make things simple, we suppose that the Place Order button is the test object to find.


Figure 2. The main window of the sample application
control an image and button on Main window

After recording the click operation on the Place Order button, you get the following hierarchical structure in the object map that is illustrated by Figure 3. You can see that the Place Order button is a child of the frame. The frame is shown as the main window, and it is where the Place Order button is located. Of course, in this example, you can simply use the find() method to locate the button. However, we'll try another way to resolve this.


Figure 3. The hierarchical structure of the object map
Button test object within the object map.

Introduction to navigation-based object recognition

Sometimes a tester finds the tested object by visual clues, such as the relative position in relationship to an obvious image. For example, you might find the Place Order button by its position relative to the cover picture of the album. This is a very useful strategy for locating the tested object. Similarly, for a given test object, which is called the anchor object, you can use the Rational Functional Tester APIs to point to any object with a given path. Using the previous example again, you can find the Place Order button by its position near a found object, the picture of the album, and a specific path. Here the term "path" is referred to as the logical distance of moving from one object node to another in the object map.

Navigate through the object map

In the Private Test Object Map for Script BaseCase window, you know that the Place Order button is a child of the main frame. Obviously, this object map does not include all of the components in the main frame. Follow these steps to get a bigger picture of the object map tree:

  1. Click Test Object and then click Insert Object(s) on the menu of the main window to open the wizard dialog.
  2. Use Object Finder to highlight the main frame and select it.
  3. Select Include all available objects on this window and click Finish.

As Figure 4 shows, now you can see that more children of the main frame are added into the object map.

Important:
Although you select the "include all" option, that option does not include all of the children of the main frame. This object map only helps you to get an idea where the Place Order button is located.


Figure 4. A more detailed hierarchical structure of the object map
Test objects added test object has many siblings

You use another tool to find all the children of the main frame. Actually, you used it just now. It is the Insert Object(s) wizard dialog (Figure 4). With this wizard, you can see all of the mappable objects. Follow these steps to locate the Place Order button.

  1. Select Test Object > Insert Object(s) on the main window to reopen the wizard dialog (Figure 5)
  2. For the Selection Method, select Test Object Browser.
  3. Find the Place Order button, guided by the hint of the hierarchical relationship given by the test object map generated just now.

Figure 5. Test Object Browser
exact position of the button in the object map.

According to the Test Object Browser, you we can see many objects that are missing in the test object map. The order of the objects in the object browser is different from those in the test object map. However, the test object map merely gives you a hint to help you find the current object in the object browser. By following the previous steps again, you can easily find the image node of the album. Then you can figure out the exact path from the image node to the button node. (See Figure 6.)


Figure 6. The path from the image to the Place Order button
path from image to Place Order in object map

As Figure 6 shows, the path from the image node to the button node can be described as follows. Notice that the index of the child is very important here.

  1. First, move up three levels to the parent.
  2. Then move down the FIFTH child of the main frame.

Use APIs to implement the navigation

You now know how to figure out the path between two test objects. In this section, you'll learn how to use APIs to automatically locate the target test object with a given path. The APIs needed for this task are summarized in Listing 2.


Listing 2. APIs required for locating test objects

/**
* This method returns an array of references to the object's mappable children.
* The references to the objects should be released by calling he unregister method.
* If the object has no mappable children, a 0-length array will be returned.
**/
TestObject[] testObject.getMappableChildren();

/**
* This method returns a reference to the parent object that appears in the object map.
* The references to the objects should be released by calling he unregister method.
**/
TestObject testObject.getMappableParent();

/**
* This method returns the topmost mappable parent object that appears in the object map.
* The references to the objects should be released by calling he unregister method.
**/
TestObject testObject.getTopMappableParent();



For simplicity, we do not use the unregister method to unregister the test objects that are iterated. The ObjectFinder class is the helper class that wraps all of the navigation operations. The UML in Figure 7 shows the relationship between these classes. Notice that the TestObjectNotLocatedException must inherit from RuntimeException for consistency.


Figure 7. The relationship of the classes with UML
The class ObjectFinder is the facade class

Considering that path example, Listing 3 shows how you can write the code to find the Place Order button:


Listing 3. Code to find the Place Order button

// This method is used to find the button Place Order
public GuiTestObject PlaceOrder() throws TestObjectNotLocatedException{
	// The path we specified to find the button from the album image
	// First move up 3 times, then move down to the fifth child
	String pathString = "P3;C5";
	Path path = null;
	try{
		path = new Path(pathString);
	}catch(IllegalPathStringException illegalpath){
		logError(illegalpath.getMessage());
	}
	
	// Assume that the imageAlbum() is already found
	return new GuiTestObject(ObjectFinder.locateTestObject(imageAlbum(), path));
}



We first specify a path string that describes the path from the album image to the Place Order button. Then we use ObjectFinder class to locate the target test object we want.


Tips for better test object recognition

We have already seen how to find a test object in variant ways. We can use the default method to find the test object. We also can use the find() method to find the test object with some given attribute/value pairs. And we can locate the test object with a given anchor object and a path. In this section, we'll discuss how to choose the right method and how to organize the source code of Rational Functional Tester project.

Choose the correct object recognition method

Obviously, the default method has a great tool support. Rational Functional Tester provides powerful tools such as Test Object Map and Script Assure, which greatly ease the complexity of script development, shortening the development time. However, it is the simplicity that some script developers complain about. They think that the tools hide some details that they want to control. The find() method is flexible and lightweight. It offers the script developers much control of the test scripts. That's why it is widely used in the scripts to substitute it for the default method. As discussed above, this method cannot cover all the cases. The navigation-based object recognition method is quite lightweight and efficient. And a key strong point is that it can be used on any occasion. However, it is sensitive to the UI structure.

We'll show you how to use the find() method along with the complementary navigation-based method while still enjoying the advantage of using the tools.

Tips for script organization

Recall the first section about Rational Functional Tester project structure. We know that all the object finding methods are implemented in the helper classes by default. For example, the default method to find the button Place Order button might look like Listing 4.


Listing 4. The default Place Order button code

public abstract class BaseCaseHelper extends RationalTestScript {
	/**
	* PlaceOrder: with default state.
	* .class : javax.swing.JButton
	* accessibleContext.accessibleName : Place Order
	* name : placeOrderButton2
	* .classIndex : 0
	*/
	protected GuiTestObject placeOrder() {
		return new GuiTestObject(getMappedTestObject("placeOrder"));
	}
	
	/**
	* Schubert4_14Jpg: with default state.
	* .class : javax.swing.JLabel
	* iconDescription : Schubert4_14.jpg
	* .classIndex : 2
	*/
	protected GuiTestObject schubert4_14Jpg() {
		return new GuiTestObject(
			getMappedTestObject("schubert4_14Jpg"));
	}
}



Then you create a helper class that extends the default helper class and overrides the default method. It would look like the code shown in Listing 5.


Listing 5. Code for the created helper class

public class BaseCaseUserHelper extends BaseCaseHelper {
	// This method is used to find the button Place Order
	public GuiTestObject PlaceOrder() throws TestObjectNotLocatedException{
		// The path we specified to find the button from the album image
		// First move up 3 times, then move down to the fifth child
		String pathString = "P3;C5";
		Path path = null;
		try{
			path = new Path(pathString);
		}catch(IllegalPathStringException illegalpath){
			logError(illegalpath.getMessage());
		}
		
		// schubert4_14Jpg() is object for the cover image
		return new GuiTestObject(
			ObjectFinder.locateTestObject(schubert4_14Jpg(), path));
	}
}
			



Finally, let the script class extend the user-defined class. In this way, you do not need to modify any existing object finding methods. You just override them, which combines the strong points of existing object finding method.



Download

DescriptionNameSizeDownload method
Sample scripts for this articleRBAT_Impl.zip10KBHTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the author

He Gu Yi

He Gu Yi is a software engineer from the IBM China Development Lab in Shanghai, China. He works on federated integration test projects, and his expertise includes enterprise content management, service-oriented architecture, and test automation.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=443116
ArticleTitle=Eliminating ambiguous cases in the recognition of test objects
publish-date=03202009
author1-email=heguyi@cn.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers