Demystifying the automation of custom controls: Part 2. A step-by-step example of using IBM Rational Functional Tester to automate custom controls

This tutorial applies the concepts that were covered in the first part of this two-part series to a real-world example. It takes you through using four methods.

Daniel Gouveia (dgouveia@us.ibm.com), Field Technical Sales Specialist, IBM

Dan Gouveia is a sales engineer for IBM. His primary focus is on the Rational functional and performance testing tools, and he works with customers to help them implement these tools in the most effective manner. Therefore, he often deals with topics such as keyword-driven testing, developing automation frameworks, and so forth.



22 January 2008

Before you start

About this tutorial

This tutorial applies the concepts that you learned in the first part of this two-part article to a real-world example. It takes you through using these four methods:

  • getProperty(String arg0)
  • setProperty(String arg0, Object arg1)
  • invoke(String arg0)
  • invoke(String arg0, String arg1, Object[] arg2)

Prerequisites

None

System requirements

None


Step 1. Determine the necessary actions, and gather the information that you will need

In the first part of this two-part article, you worked through three steps to learn the basics of how to use IBM® Rational® Functional Tester with custom controls. The conceptual content of those steps provides the means to deal with almost any custom controls -- unless the controls do not expose the information (properties and methods, for instance) that automation tools need.

This tutorial applies those concepts to a real-world example of using these four methods:

  • getProperty(String arg0)
  • setProperty(String arg0, Object arg1)
  • invoke(String arg0)
  • invoke(String arg0, String arg1, Object[] arg2)

The description of these methods is based on using the Syncfusion.Windows.Forms.Tools.TreeViewAd control (see Figure 1). This is a third-party, custom control developed by Syncfusion. Basically, it acts as a typical Microsoft® .NET tree control. Of course, it has been extended to offer more robust capabilities by embedding other controls, such as radio buttons, check boxes, and so forth.

Figure 1. Syncfusion.Windows.Forms.Tools.TreeViewAd object
Syncfusion.Windows.Forms.Tools.TreeViewAd object

This control is an excellent example of the types of custom controls that you might find yourself trying to automate. You can use the techniques in this article for any other custom control that you might encounter (other than the caveat mentioned in the first paragraph), whether it is .NET, Java™ technology, a third-party control, or developed in-house.

In the preceding article, your first step was to write down the actions that you wanted to perform on this custom control. A short list of actions might look something like this one:

  1. Traverse top-level nodes
  2. Get the text of the selected node
  3. Toggle the check box of a node
  4. Expand all nodes
  5. Collapse all nodes
  6. Get the number of top-level nodes

A spreadsheet works well to capture these actions. The example here is rather simple, but as you encounter more custom controls, you'll need to have a well-organized document that contains this information. Figure 2 shows a Microsoft® Excel® spreadsheet, called CustomObjectAutomation.xls, that shows the details of how to store this information, with these columns:

  • Control Name
  • Control Default Behavior
  • Actions to Invoke
Figure 2. An Excel spreadsheet with details of your automation needs (a work in progress)
An Excel spreadsheet with details of your automation needs (a work in progress)

Creating a visual record like this has several advantages:

  • It gives you a great way to document the work that you are doing for future reference.
  • It provides a way to determine the scope of the amount of work to do.
  • It can also be a valuable tool for figuring out the cost-benefit analysis to decide whether or not to automate a particular custom control.

Step 2. Translate the information into properties that custom controls can use

Thanks to what you accomplished in the first step, you now have an asset that provides you with some very useful information. Remembering back to the previous article, step number two is where you need to translate this information into something that the actual custom controls can understand. Basically, you need to find out the code that matches the actions that you want the controls to perform. If you recall, there are a few sources that were mentioned:

  • You can work with your developer to get this information.
  • You can get the API specifications for the controls.
  • You can use the Test Object Inspector in Rational Functional Tester.

Regardless of the source, this will be technical jargon. It's good to add this technical jargon to your original documentation (the spreadsheet that you saw in Step 1).

Sometimes, it can be difficult getting a developer's attention. Further, it can sometimes prove to be a daunting task to locate the right API specifications for the different controls that you are working with. If either is the case, the Test Object Inspector is a great place to start. In fact, it helps to consider it as the first place to acquire information. After all, it allows you to see the inner workings of the controls from the perspective of Rational Functional Tester.

  1. To launch the Test Object Inspector, select Run > Test Object Inspector. Figure 3 shows what it looks like initially.
Figure 3. Test Object Inspector (initial view)
Test Object Inspector (initial view)

You see a modal dialog box on top of the Test Object Inspector. This simply instructs you on how to use the tool:

  1. Basically, you simply hover your mouse cursor over the control that you want, and then hit the Shift key to freeze the information.
  2. If you want to recapture the information, you press the Shift key again. This will unfreeze the tool, allowing you to hover your cursor over other controls. Figure 4 shows the information captured by the Test Object Inspector when the cursor hovers over the Syncfusion.Windows.Forms.Tools.TreeViewAd object.
Figure 4. Test Object Inspector with the object data captured
Test Object Inspector with the object data captured

The active icons highlighted in the red box in Figure 4 show the different information that you can access (in this order, from left to right):

  1. Icon that represents directory (tree) structure: Parent hierarchy
  2. Icon with an up arrow: Show Inheritance hierarchy
  3. Icon with a rectangle and a circle: Test Object Value properties
  4. Icon with a red X: Test Object Nonvalue properties
  5. Icon with the letter M: Method information

The last three icons (Test Object Value properties, Test Object Nonvalue properties, and Method Information) are where you'll often find the most useful information. An object returns either Value or Nonvalue properties:

  • A Value property provides something that you can work with right away, such as a Boolean result (true or false), numeric values, strings, and so forth.
  • A Nonvalue property provides something that needs further processing (coding, for instance). These are typically custom objects that get acquired through property values.

Methods are requests that you can impose on an object through custom coding. Hierarchy information becomes necessary when you need to access information about an object's child (subordinate) object.

You now have access to the information that you need.

  1. Now, sort through this information to find the exact property or method that maps to the action that you need to perform. This can be a difficult or time-consuming process. If you recall, the previous article described this as a process of trial and error. Simply put, you may need to (and most likely will) go through several different properties and methods that you feel map to the actions in your spreadsheet. The best way to do this is to narrow things down by the names of the properties and methods, as well as by the values that they return; which is information that you can get from the Test Object Inspector. You may need to do deeper research if the names and return values don't help. This is where you rely on the knowledge of a developer or on the API specifications.

Types of properties and methods

For this example, you would eventually turn up the following information for each of your desired actions:

TopVisibleNode property

The Test Object Inspector shows you that there is a Nonvalue property called TopVisibleNode (Figure 5). This property gives you a starting point (for example, Node #1) for your movement across the tree. It returns a TreeNodeAdv object, which alerts you that there will be a bit more coding involved.

Figure 5. Test Object Inspector with the TopVisibleNode property selected
Test Object Inspector with the TopVisibleNode property selected

Add this information to your spreadsheetAdd this to your spreadsheet.

TreeNodeAdv object

Probe deeper into the TreeNodeAdv object. You need to know how to move from one tree node to the next. The Test Object Inspector does not provide you any information about this; it provides only data on the Syncfusion.Windows.Forms.Tools.TreeViewAd parent object. To get the TreeNodeAdv properties and methods, turn to the API specification. The specification will show you all of the properties and methods that are available for the desired object. In this case, you find that the NextNode property is available (Figure 6).

Figure 6. API Specification with the TreeNodeAdv object's NextNode property selected
API Specification with the TreeNodeAdv object

Add this information to your spreadsheetAdd this to your spreadsheet.

SelectedNode property

Now that you know how to get the next node in the tree, you need to figure out how to actually select the nodes. This is something handled at the tree level. You can return to the Test Object Inspector to find the necessary data for this task. There is a SelectedNode property that you can take advantage of (Figure 7).

Figure 7. Test Object Inspector with the SelectedNode property selected
Test Object Inspector with the SelectedNode property selected

You can use this property to set the next selected node.

Add this information to your spreadsheetAdd this to your spreadsheet.

Text property

To find out how to get the text of a tree node, you are required to use the API specification. Figure 8 shows that the TreeNodeAdv object offers a Text property.

Figure 8. API specification with the TreeNodeAdv object's Text property selected
API specification with the TreeNodeAdv object

This property gets or sets the text of the node.

Add this information to your spreadsheetAdd this to your spreadsheet.

CheckState property

Because you need to toggle a check box object that is associated with a tree node, you need to continue reviewing the API specification for the TreeNodeAdv object. Figure 9 reveals that a property called CheckState exists.

Figure 9. API specification with TreeNodeAdv object's CheckState property selected
API specification with TreeNodeAdv object

This property gets or sets the CheckState of the node. Choose this property over the Checked property, because it gives you the ability to set whether the box is checked or not (versus querying whether the box is checked).

Add this information to your spreadsheetAdd this to your spreadsheet.

ExpandAll() method

Returning to the Test Object Inspector, you see that there is a method called ExpandAll(), as Figure 10 shows.

Figure 10. Test Object Inspector with the ExpandAll() method selected
Test Object Inspector with the ExpandAll() method selected

ExpandAll() is a simple method that will carry out the Expand All Nodes action.

Add this information to your spreadsheetAdd this to your spreadsheet.

CollapseAll() method

The Test Object Inspector shows you a corresponding method called CollapseAll() (Figure 11).

Figure 11. Test Object Inspector with the CollapseAll() method selected
Test Object Inspector with the CollapseAll() method selected

Much like the ExpandAll() method, CollapseAll() is a straight-forward method that enables the Collapse All Nodes action.

Add this information to your spreadsheetAdd this to your spreadsheet.

get_Nodes method

Lastly, you find that there is a get_Nodes method (Figure 12).

Figure 12. Test Object Inspector with the get_Nodes() method selected
Test Object Inspector with the get_Nodes() method selected

This method returns the top-level nodes within in a custom object called TreeNodeAdvCollection. This means that you need to consult the API specification and read the information provided for this object. Look for a Count property, because you simply need to acquire the number of top-level nodes to satisfy your counting action. Unfortunately, no such property exists in the specification. One trick that you can use is to see what custom properties a developer may have added to the object. You can write a small chunk of code to handle this, as the code snippet in Listing 1 shows:

Listing 1. Code to find what custom properties that a developer added, if anything
//invoking the "get_Nodes()" method returns a TreeNodeAdvCollection object
TestObject nodes = (TestObject)treeViewAdv1net().invoke ("get_Nodes");

//find out ALL of the properties (including custom-added) for the TreeNodeAdvCollection
Hashtable h = nodes.getProperties();
Iterator i = h.entrySet().iterator();
//while
(i.hasNext())
{ System.out.print1n(i.next());
}

These six lines of code, excluding comments, will produce a list of properties (and their current values) for you to review, as you see in Figure 13.

Figure 13. Properties returned by the custom code
Properties returned by the custom code

These properties appear in the Console window of Rational Functional Tester. Here, unlike the API specification, a Count property exists. This tells you the number of top-level nodes, so be sure to document that (you know where by now).

You have now gathered all of the information necessary to implement your desired actions. Your spreadsheet should show all of the data that you've compiled; therefore, it should now look like Figure 14, which has a fourth column added at the right, with a heading of Object Method or Property..

Figure 14. Excel spreadsheet compilation of the data that you captured during your research
Excel spreadsheet compilation of the data that you captured during your research

This detailed documentation will give you an excellent idea of how to instruct Rational Functional Tester to automate your custom object's actions.


Step 3. Develop your test scripts

Now you are ready to begin developing your scripts. For this tutorial, you will create two scripts.

  • The first uses the Rational Functional Tester getProperty() and setProperty() methods.
  • The other focuses primarily on the tool's invoke() methods.

Add the top-level test objects to your script

Regardless of whether you use the getProperty(), setProperty(), or invoke() method, you need to ensure that the top-level test object (treeViewAdv1net) is registered to your script.

  1. First, create an empty script by right-clicking on either your project or project folder and selecting Add Empty Script (Figure 15).
Figure 15. Creating an empty script
Creating an empty script
  1. When you have an empty script, you need to register the custom tree control as a test object in your script. To do that, right-click the Test Objects folder (in the Script Explorer view of the newly created script) and select Insert Test Object (Figure 16).
Figure 16. Adding a test object to a script
Adding a test object to a script
  1. This brings up the Test Object Finder. Use that now to select the tree. This places the custom tree object information into the Test Object Finder (Figure 17).
Figure 17. Test Object Inspector with selected object information
Test Object Inspector with selected object information
  1. Click Finish to add this object to your script (Figure 18).
Figure 18. Empty script displaying the newly added Test Object (Syncfusion.Windows.Forms.Tools.TreeViewAd)
Empty script displaying the newly added Test Object

Create the custom script

Now that you know how to add objects to your scripts, you are ready to start creating the custom script.

Functional Tester getProperty() and setProperty() script

The script displayed in Figure 18 shows multiple uses of the getProperty() and setProperty() methods. The actual calls to these methods are color-coded to show their relationships.

By using the information in your spreadsheet, you see that your first invocation of getProperty(), shown in Listing 2, acquires the top node in the tree (the red highlighting).

Listing 2. First invocation of the getProperty method
TestObject treeNode = (TestObject)treeViewAdv1net().getProperty("TopVisibleNode");

This starts everything off. You know that when you capture this property, it returns a tree node. Rational Functional Tester enables you to capture this as a test object so that you can manipulate it later. For instance, you see that the second use of getProperty() (highlighted in blue in the screen capture) allows you to capture the text of this node, as you see in Listing 3.

Listing 3. Second invocation of the getProperty method
String nodeText = treeNode.getProperty("Text").toString();

To traverse the nodes of the tree in another one of your documented tasks, you set up a loop by using a combination of getProperty() and setProperty() methods (green highlight) shown in Listing 4.

  1. First, you call the setProperty() method to set the selected node to be your test object (remember, you get that from your first getProperty() call to get the first visible node). This gives you an object to work with (to get data from it, for example). Tip: Remember, you get that from your first getProperty() call to get the first visible node.
  2. Then you call the getProperty() method to attain the next node in the tree, getProperty("NextNode").
Listing 4. Using the setProperty() method to set the selected node and the getProperty() method to acquire the next available node in the tree
treeViewAdv1net().setProperty("SelectedNode",treeNode);
treeNode = (TestObject)treeNode.getProperty("NextNode");
  1. Store the returned node in your test object, treeNode. If the treeNode happens to be Baby Vaccines, the script looks at the associated check box. If it is selected, the script deselects it; conversely, if it is selected, the script unchecks it (see the purple highlighted area in the screen capture and shown Listing 5).
Listing 5. Script selects or deselects the test object check box according to content of test object
// for the case where the checkbox IS NOT checked
if (treeNode.getProperty("Checked").toString().equalsIgnoreCase("false")){
    treeNode.setProperty("CheckState","Checked");

//then for case where the checkbox IS checked
else{treeNode.setProperty("CheckState","Unchecked");
  1. Continue looping until there are no more top-level nodes left (meaning that you get a null response).

To summarize, by using the getProperty() and setProperty() methods, this script (Figure 19) enables you to accomplish these three tasks for this custom control:

  • Traverse the tree (top-level nodes)
  • Get the text of the selected node
  • Toggle the check box of a node
Figure 19. getProperty() and setProperty() script
getProperty() and setProperty() script

Rational Functional Tester invoke() script

The script in Figure 20 shows you three uses for the Rational Functional Tester invoke() method.

Figure 20. The invoke() script
The invoke() script

An Alternative invoke() method

Another invoke() method offered by Rational Functional Tester requires you to pass these three arguments to it:

  • Method name (as String)
  • Method signature (as String)
  • Method arguments (as Object array)

You would use this version of the invoke method (String object name, String object signature, Object[] arguments) if the custom object method required you to pass arguments to it. Your research turned up three custom object methods that do not require arguments. Therefore, you can use the simpler invoke() method for this exercise.

The script's first highlighted statement (see Figure 20) simply calls invoke() and passes the custom tree control's ExpandAll method (the red highlighted area, which is also shown in Listing 6). As its name implies, this expands the entire tree.

Listing 6. Invoking the ExpandAll method
treeViewAdv1net().invoke("ExpandAll");

Conversely, you see that collapsing all of the nodes in the tree is easily accomplished by calling invoke() and passing in the CollapseAll method (the blue highlight in the screen capture, also shown in Listing 7).

Listing 7. Invoking the CollapseAll method
treeViewAdv1net().invoke("CollapseAll");
  1. Lastly, you need to get a count of all the top-level nodes. This is where you'll need the combination of invoke() and getProperty() methods (the green highlights, also shown in Listing 8).
Listing 8. Code for getting a count of the top-level nodes
TestObject nodes = (TestObject)treeViewAdv1net().invoke("get_Nodes");
Integer nodeCount = (Integer)nodes.getProperty("Count");
  1. First, call invoke() by using the tree controls get_Nodes property. The research that is documented in the spreadsheet tells you that this method returns a collection of tree nodes contained in the TreeNodeAdvCollection object.
  2. Capture and manipulate the return value of invoke(), using the TestObject class.
  3. After you have this captured as a TestObject, you can then simply call the getProperty() method by using the Count property.

In summary, the script in Figure 20 enables you to accomplish the following three tasks for this custom control:

  • Expand the tree nodes
  • Collapse the tree nodes
  • Determine the number of top-level tree nodes

Whenever you create test objects, such as TestObject to1 = object.invoke('some_method') or TestObject to2 = object.getProperty('some_property'), you need to ensure that they are cleaned up after use. To do this, you call the unregister() method. The code in Listing 9 shows what that call looks like.

Listing 9. Code for using the unregister() method
treeNode.unregister();

The treeNode.unregister(); line shows how the treeNode test object invokes the unregister() method. This will ensure that it is cleaned up after the script has finished running.

Tip:
To ensure that your script is running as you intended, use the JOptionPane.showMessageDialog() method, which enables you to use dialog boxes that contain custom messages. These messages come in handy not only for displaying information, such as the node count that you received, but also for pausing scripts when they are running. These message dialogs enable you to see and monitor the behavior of the custom control after the script has run a command. A great example of this is with the ExpandAll and CollapseAll methods, although their activities occur so fast that it is hard to follow what happened.

As you construct your scripts, you may want to consider modifying your spreadsheet (remember that?), adding the Rational Functional Tester object scripting commands that you used. This makes your documentation consistent. The resulting spreadsheet would look like the final one in Figure 21.

Figure 21. The completed Excel spreadsheet
The completed Excel spreadsheet

Prepare scripts for reuse

You have now seen how to apply the concepts that you read about in the first article. Between these two articles, you can gain an understanding of the level of work involved. This is a non-trivial process that requires solid scripting skills and a good understanding of the custom objects

Moving forward, it will help to think about the best ways to manage this type of scripting. Think in terms of developing reusable methods that can be called from any script, rather than writing the same code in every script.

Resources

Learn

  • Get an Introduction to IBM Rational Functional Tester 7.0. The IBM Rational Functional Tester tool automates testing Java, .NET, and Web-based applications. Starting with Version 7.0, it includes support extensions for both Siebel and SAP, plus integration with IBM Rational ClearQuest, support for the Eclipse Test and Performance Tools Platform (TPTP) logs, and support for testing HTML applications with Mozilla Firefox. This article explains these new features and capabilities.
  • Visit the Rational Functional Tester area on developerWorks for introductory to in-depth information.
  • Visit the Rational software area on developerWorks for technical resources and best practices for Rational Software Delivery Platform products.
  • Subscribe to the developerWorks Rational zone newsletter. Keep up with developerWorks Rational content. You'll receive updates on the latest technical resources and best practices for the Rational Software Delivery Platform.
  • Subscribe to the Rational Edge e-zine for articles on the concepts behind effective software development.
  • Browse the technology bookstore for books on these and other technical topics.

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=282330
ArticleTitle=Demystifying the automation of custom controls: Part 2. A step-by-step example of using IBM Rational Functional Tester to automate custom controls
publish-date=01222008