Skip to main content

skip to main content

developerWorks  >  Rational  >

Advanced IBM Rational XDE Tester topics: working with the Object Map

developerWorks
Document options

Document options requiring JavaScript are not displayed


Rate this page

Help us improve this content


Level: Introductory

Bill Grant, Senior IT Specialist, IBM Rational Software

10 Jun 2004

Even with the new object map employed by IBM Rational XDE Tester, your scripts may stil have trouble recognizing objects in situations where an object's recognition properties are dynamic and where object hierarchies are dynamic. This article describes what you can do to handle these situations.

Editor's note: The name of IBM® Rational® XDE™ Tester has been changed to IBM® Rational® Functional Tester for Java™ and Web since this article was written. The content applies to version 2003 and later of the software.

The new object map employed by IBM® Rational® XDE™ Tester is a great facility for ensuring that your scripts are resilient to changes, but there are still some situations that may cause scripts to have trouble recognizing objects. This article, one of a series covering advanced topics in XDE Tester, describes two of these situations and what you can do to handle them. By following along as we develop an example script, you'll learn how to deal with scenarios where an object's recognition properties are dynamic and where object hierarchies are dynamic.

Getting Set Up

This article builds on concepts introduced in "Creating a Super Helper Class in Rational XDE Tester" by Dennis Schultz, so you may want to read that article before proceeding further. Be sure that you've prepared your environment to record scripts as described in "Advanced XDE Tester Topics: Leveraging the Power of Regular Expressions." In addition, copy the files 1.htm , 2.htm , and 3.htm to a known location (C:\Test Project would be fine) and then set up these sample applications in the Application Configuration Tool as Web-1, Web-2, and Web-3. The window should look something like Figure 1.

Application Configuration Tool window with the sample applications set up
Figure 1: Application Configuration Tool window with the sample applications set up



Back to top


A Word About Object Maps

XDE Tester offers you the ability to manage a centralized object map. Without this object map, a change to a control name would require a change to any automated scripts that used that control. This could lead to a lot of unnecessary rework.

This usually isn't a major issue with thick-client applications (although there certainly are exceptions) because (1) most developers don't change the names of controls often, as this can break a lot of existing code and is generally considered bad practice, and (2) the layout of screens tends not to change dynamically. But the rules change for thin-client Web applications. Pages are created dynamically, many controls aren't given names (it isn't a requirement in HTML), and a lot more developers may be contributing to one page's development than in traditional thick-client development.

As more and more applications are developed on the Web, it's critical that we leverage object maps to keep our scripts reusable with as little rework as possible.



Back to top


Handling Dynamic Object Recognition Properties

One thing that happens a lot on the Web is that pages of the same type have different URLs and/or different titles. For example, when I perform a search for "digital cameras" on Yahoo.com, the title of the page that's returned is "Yahoo! Search Results for digital cameras" and the URL of the page is http://search.yahoo.com/search?p=digital+cameras&ei=UTF-8&fr=fp-top. When I perform a search for something else, the title and the URL change even though the same type of page (a search result page) is returned. If I were testing the Yahoo Web application, I'd want to be able to treat all of the search result pages as the same page, since fundamentally they are the same page. However, many of the pages' properties would tell an automation tool that they're different.

We can see a simplified demonstration of this same phenomenon with our test pages, seen in our applications Web-1 and Web-2, as shown in Figure 2.

The pages generated by Web-1 and Web-2
Figure 2: The pages generated by Web-1 and Web-2

If you ignore the links at the bottom, the pages look identical except for differences in title and URL. To demonstrate how to handle object recognition in this situation, we'll record a simple script against Example 1 and play it back against Example 2, noting the warnings due to failed recognition that show up in our log. Then we'll take a look at the object map and modify it so that we can play back our basic script against any number of Example pages without raising a warning.

Record the Basic Script

We'll start our work by recording a new script called Web1, using a private object map. Perform the following steps:

  1. Start application Web-1.
  2. Put a wait state on the document, Example1. (A wait state tells XDE Tester to wait until the document appears before continuing.) You create a wait state by running the Verification Point and Action Wizard as usual. Drag the hand over any area on the page that isn't a control (for example, the white space at the bottom of the page). Then click the Wait for Object tab in the wizard. Uncheck "Use the defaults" and enter 5 for the Maximum Wait Time and 1 for the Check Interval (see Figure 3).

Creating a wait state
Figure 3: Creating a wait state

  1. Click Button.
  2. Click OK on the pop-up window.
  3. Close the browser window.

Your testMain function should look something like this:

public void testMain (Object[] args) 
{
 startApp("Web-1");

 // HTML Browser
 // Document: Example 1: file://C:\Test%20Project\1.htm
 Document_Example1().waitForExistence(5.0, 1.0);
 Button_Button().click();

 // 
 Dialog_HtmlDialogButtonOK().click();

 // HTML Browser
 Browser_htmlBrowser(Document_Example1(),MAY_EXIT).close();
}

Run the Script

Play back the script to ensure that it works as advertised.

To demonstrate the issue of dynamic object recognition properties, we'll next play back the script against Web-2. In Web-2, the document's title is Example 2 and its URL is file://C:\Test%20Project\2.htm.

Back in the script, change the line

startApp("Web-1");

to

startApp("Web-2");

and run the script again.

You may be surprised to find out that the script executes correctly, albeit at a slower pace. What basically happened is that by using ScriptAssure to determine "close" property matches, XDE Tester determined that the new document matched the original closely enough to let the script proceed. It also didn't find any other documents that were anywhere near a match. See XDE Tester help for more information on this capability.

Even though the script executes, our playback log shows a couple of warnings due to failed recognition, as shown in Figure 4. The warnings relate to the wait state and the button click.

Warnings shown in the playback log
Figure 4: Warnings shown in the playback log

Modify the Object Map

Now let's take a look at the object map for our script (see Figure 5). To get the map, double-click the Private Test Object Map icon in the XDE Tester Script Explorer on the right.

Object map for our script Web1
Figure 5: Object map for our script Web1

The first top-level node refers to the pop-up window (and the OK button we used to dismiss it). The second refers to our browser. Ignoring the browser toolbar, you can see that the tree appears as follows:

+ The browser
|---+ The document
 |---+ The table
  |---+ The form
   |---+ The button

Object recognition in XDE Tester relies not only on the object itself but on all of the object's parents as well. Looking more closely at the document object (highlighted in the figure), we see its three recognition properties:

.class = Html.HtmlDocument
.title = Example 1
.url = file://C:\Test%20Project\1.htm

To understand why object recognition failed when we played back our script against Web-2, we can add controls side by side in the same map to see what the differences are. Right now our map refers to the document from Web-1 (1.htm). We'll add in the document from Web-2 (2.htm) to compare the two and make a decision about how we can ensure that XDE Tester determines that both pages are the same.

We know that the first thing to get a warning is the wait state on the document, so let's add that object to the map. In the object map, click Test Object > Insert Object(s) and drag the hand over the Example2 document. Leave the default, "Just the selected object," and click Finish. The Example2 document is added to the map, indicating that it's recognized differently from our original Example 1 page. Specifically, the title and URL properties are different. You can see the details in Figure 6.

The recognition properties of the Example 2 page
Figure 6: The recognition properties of the Example 2 page

Follow the same procedure to insert the button object on the Example 2 page into the object map. When you do that, you should see that entries for the table, form, and button all appear under our new document, Example2, in the object map. See Figure 7.

Table, form, and button entries for Example 2 added to the object map
Figure 7: Table, form, and button entries for Example 2 added to the object map

Now that we've added these objects from the Example 2 page to our object map for the Web1 script, we can play back the script against our Web-2 application without getting any warnings due to failed object recognition. But this solution of adding objects to our map so that we can run the same script against a number of pages of the same type simply isn't going to cut it in the real world. Yahoo searches can return an infinite number of possible pages, and we don't want to map each one.

Instead, what we need to do is modify the recognition properties of Example1 in the object map to be flexible enough to handle

  • a title that contains the word Example and then any one-digit number, and
  • a file that's found at c:\Test Project\{any one-digit number}.htm.

These are the requirements for our example. You'll need to use intuition about how the application you're testing works to give you guidance on how to map yours.

Let's first delete the node we just added (Example2), and then set the title and URL property values of Example1 to the following:

.title > Example \d
.url > file://c:\Test%20Project\\d.htm

You can set each property by right-clicking it, clicking Convert Value to Regular Expression, double-clicking to edit, and replacing the number 1 with \d (for any digit).

When you play back the script now, you should find the script running as fast as it did the first time. Try playing it against Web-1 to ensure it still works there, too.



Back to top


Handling Dynamic Object Hierarchies

You've just learned how to handle a testing situation where an object's recognition properties are dynamic, but what about a situation where the whole object hierarchy changes? To demonstrate this situation, let's compare the example pages generated by our applications Web-1 and Web-3, as shown in Figure 8.

The pages generated by Web-1 and Web-3
Figure 8: The pages generated by Web-1 and Web-3

Again, if we ignore the links at the bottom, the pages differ in title and URL, and they also differ in that the Example 3 page has a nested table. Remember that XDE Tester recognizes objects not just by their own individual properties but also by the properties of their ancestors. So the button on Example 3 (which is inside a table that's inside a table) is recognized differently from the button on Example 1 (which is inside a table).

You might ask yourself, Where would this situation occur in the real world? A much more complex example than the one illustrated in Figure 8 involves Web pages that employ portals. On such pages, users have tremendous flexibility in specifying where individual portal components, or portlets, are rendered. Figure 9 is an example of one of IBM's demo portal sites, JK Enterprises. Personalization capabilities allow users to lay out their portals in very different ways even though the individual portlets like My News and My Stocks may function in the same way. Scripts need to be resilient to these changes, and using the technique I'm going to describe can help.

IBM's demo portal site for JK Enterprises
Figure 9: IBM's demo portal site for JK Enterprises
(click here to enlarge)

One way to handle dynamic object hierarchies is to use the event facilities of XDE Tester to look for just the object you want to interact with (instead of being concerned with the whole object hierarchy) if an initial recognition fails. If we find that object uniquely, we'll use that object, but if we find two or more objects that fit the properties, we'll consider this a failed search. This is the approach we'll use as we modify our basic script to find a button uniquely.

Modify the Script

Let's modify our Web1 script by adding the following code below testMain. This new code should ultimately be placed in a super helper class (as described in Dennis Schultz's article "Creating a Super Helper Class in Rational XDE Tester").

public void onObjectNotFound(ITestObjectMethodState TestObjectMethodState)
 {
 TestObject theFoundObject[] = new TestObject[1];
 int iNumberFound[] = new int[1];
 iNumberFound[0] = 0;
 theFoundObject[0] = getDomains()[0]; // Put any object in there to avoid 
                                      // nulls

 TestObject[] objectsToCheck;
 for (int i=0; i<getDomains().length; i++)
 {
  objectsToCheck = getDomains()[i].getTopObjects();
  findTheObject(TestObjectMethodState.getTestObject(), objectsToCheck,
   theFoundObject, iNumberFound);
 }

 if (iNumberFound[0] == 0)
 {
  // Couldn't find the object
  logInfo("Couldn't find the object...");
 } else if (iNumberFound[0] == 1 )
 {
  TestObjectMethodState.setFoundTestObject(theFoundObject[0]);
 } else if (iNumberFound[0] > 1 )
 {
  logInfo("Found more than one object which matches the criteria");
 }
}

private void findTheObject(TestObject objectToFind,
 TestObject[] objectsToCheck, TestObject[] theFoundObject,
 int iNumberFound[])
{
 // Note: the counter, iNumberFound[], is in an array because it is the only
 // easy way to pass by reference in Java...
 for (int i=0; i<objectsToCheck.length; i++)
 {
  if (compareObjectProperty(objectToFind, objectsToCheck[i], ".class"))
  {
   if 
    (objectsToCheck[i].getProperty(".class").equals("Html.INPUT.button"))
   {
    // Test only the .name property
    if (compareObjectProperty(objectToFind, objectsToCheck[i], ".name"))
    {
     logInfo("Found: " + objectsToCheck[i].getProperty(".name"));
     theFoundObject[0] = objectsToCheck[i];
     iNumberFound[0]++;
    }
   } // Add "else if's" for other conditions for other types...
  }
  if (objectsToCheck[i].getChildren().length > 0 )
  {
   findTheObject(objectToFind, objectsToCheck[i].getChildren(),
    theFoundObject, iNumberFound);
  }
 }
}

private boolean compareObjectProperty(TestObject mappedObject,
 TestObject candidateObject, String propertyName)
{
 if (mappedObject.getPropertyFromMap(propertyName).equals
  (candidateObject.getProperty(propertyName)))
   return true;

 return false;
}

This new code will help us handle a situation where recognition can't be made using the standard map (and object hierarchy). The logic is as follows:

  1. Try to find the object as we would under normal circumstances.
  2. If an object can't be found, execute the onObjectNotFound method we created. (In our simple example, we'll handle only buttons and see if we can find another button that has the same name as the one we're looking for.)
  3. If we find only one button that matches our name, we'll use that one and continue.
  4. If we find zero or more than one, we'll log an error, won't use any of the controls, and will try to continue.

Although this code does the job of uniquely finding a button, you should realize that a full solution would require investigation of which properties should be included for a unique representation of that control. There are three properties that are fairly common among HTML objects that you'd test:

  • the class (for example, Html.INPUT.button, Html.TABLE)
  • the ID
  • the name

Another property that's also sometimes important is the value property. For example, with radio buttons both the name and the value can uniquely identify a radio button.

Run the Script

When you run the new script you'll see that the object can't be found using the regular object map. Instead, our onObjectNotFound method is fired, and by iterating through all the controls it's able to find another button with the same name as the one it was looking for.



Back to top


Wrap-Up

Our example XDE Tester script has demonstrated how to handle dynamic object recognition properties and dynamic object hierarchies. You'll typically have to deal with these in situations where you're testing portals or dynamic Web pages (such as search result pages). Recently I worked with a customer that managed many hotel-specific pages where the pages were mostly the same but the title, images, and some text were different. Using these techniques makes maintenance far easier in such cases.



Back to top


References



About the author

Bill Grant is a Senior IT Specialist for IBM Rational Software based in New York City. His primary focus is on the application of modern software engineering practices. Bill has worked with numerous software development teams in consulting, mentoring, and training capacities. His background includes leading development projects employing technologies including C++, Visual Basic, Delphi, and Java. His expertise extends to all aspects of the software development lifecycle -- change management, requirements management, object-oriented analysis and design, functional and performance testing, and project and process management. He can be reached by e-mail.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top