How to turn off the RFT 7.0.1 Exception Window

Since the 7.0.1 release of Rational Functional Tester, a very frustrating feature has crept in… the “Exception Window”. What happens is; whenever an exception occurs, instead of it being thrown and caught by standard try{...}catch(Exception e){} code, RFT pauses execution of the test, and displays the shiny new “Exception Window”. Whilst this has probably been included because it looks clever in product demos, it stands the idea of test automation on its head: If a test fails, that’s fine; just go on with the next one. If the test run pauses and doesn’t continue until a human “fixes” the problem, the benefits of automation are almost gone. After a bit of searching, here’s how to turn off this highly annoying feature:

com.rational.test.ft.util.OptionManager.set("rt.interactive", new Boolean(false));

Simple as that. Include that line early on in your test suite/framework setup code, and you’ll be rid of this daft new feature.

RFT Script Options

Rational Functional Tester provides access to a lot of the “global” values that are used in execution. Things like, how long the “waitForExistence” period is. How long to wait between polling for an object while waiting for it. They’re all documented in the Functional Tester API – do a search for “IOptionName“. The help will give details on the option name, and the kind of variable the option is stored in (eg: int, double, String, etc).

An example is the one mentioned above: how long a “waitForExistence” period is. The option name is: “MAXIMUM_WAIT_FOR_EXISTENCE“. The value represents the number of seconds – the default being “2.0″ seconds. Here’s how to get the value:

public static double dWaitTime = ((Double)RationalTestScript.getOption(IOptionName.MAXIMUM_WAIT_FOR_EXISTENCE)).doubleValue();

As you can see, the IOptionName class contains a bunch of static variables (eg: “IOptionName.MAXIMUM_WAIT_FOR_EXISTENCE“). Those variables contain other strings (which probably means that this bit can be circumvented – but that’s probably a bad idea long term) which when passed to the static “getOption” method of the “RationalTestScript” class return an object with the desired variable. The last step is to cast the object to the kind of data you know it is (mentioned in the Help, eg: “The maximum amount of time to wait between retries while waiting for an object to come into existence. This is a double.”), in this case, a “double“. In the above example it was easiest done using the static “parseDouble” method of the “Double” class.

This method works for any of the static strings mentioned in the “IOptionName” help file. Enjoy.

Method to get a table row as a Hashtable

First post of the new year… I hope it’s coherant. And it’s to do with dealing with rows in tables. Another of RFT’s weak points.

This post contains code that will return a hashtable with a specified row’s data. The hashtable’s keys are the column names, and the values are the values in the cell. The value type is whatever the object type of the cell is.

To use it, paste the code into wherever you use tables and want to get row data from them. Call the method and pass in the table to interrogate and the row number to fetch. Easy!

I know, I know… the code could be much improved. Please send in your fixes. Thanks!


/*
* Copyright (c) 2006, Nathaniel Ritmeyer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* - Neither the name of natontesting.com nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* www.natontesting.com
*/
public Hashtable getObjectsForRow(GuiSubitemTestObject tblTargetTable, int iRowNumber) throws Exception
{
//set up a hashtable to store our results
Hashtable htKeyValuePairs = new Hashtable();

//get the test data from the table so that we can use it
ITestDataTable itdt = (ITestDataTable)tblTargetTable.getTestData(“contents”);

//get the number of columns; we’re going to use this for the loop
int iNumberOfColumns = itdt.getColumnCount();

//loop through each column
for(int iColumnCounter = 0; iColumnCounter < iNumberOfColumns; iColumnCounter++)
{
//get the column name (as a string) and the corresponding cell value (as an object)
String sColumnName = itdt.getColumnHeader(iColumnCounter).toString();
//with the: iRowNumber – 1, the “-1″ is there because all these methods are 1-based
Object oCellValue = itdt.getCell(iRowNumber – 1, iColumnCounter);

//if either the column name or the cell == null, set them to a blank
//string, or the hashtable won’t be able to deal with it
if(sColumnName == null)
{
sColumnName = “”;
}
if(oCellValue == null)
{
oCellValue = “”;
}

//add the column name and cell value to the hashtable
htKeyValuePairs.put(sColumnName, oCellValue);
}

//return the hashtable
return htKeyValuePairs;
}

Methods to deal with trees in RFT

Dealing with trees in Rational Functional Tester can be a pain. And there isn’t much good code out there to help. So, I’ve put together a few methods which could serve as a good starting point for you to build your own tree management class. The code isn’t all that efficient, but it’s well commented so you can quickly identify what you may want to change.

I wanted to have a method where I could just pass in a tree object and a regular expression, and RFT would click the right node for me. I also wanted to pass in a regular expression and have the tree navigation path for the matching node returned to me (eg: passing in “Piano” and getting Composers->Mozart->Concerto in D for Piano returned to me…). I also wanted to be able to spit out all the navigation paths of a tree to the console.

What follows is a class called TreeManager, which contains the following methods:

  • getPathForFirstNodeWithRegex
  • clickNodeWithPath
  • clickNodeMatchingRegex
  • printTreeNavigationPaths
  • arrayOfNavigationPaths
  • getPathForAllNodes

With the tree object in the ClassicsJavaA demo mapped as tree2, the result of running the printTreeNavigationPaths method is:

Composers
Composers->Schubert
Composers->Schubert->String Quartets Nos. 4 & 14
Composers->Schubert->Die schone Mullerin, Op. 25
Composers->Schubert->Symphonies Nos. 5 & 9
Composers->Haydn
Composers->Haydn->Symphonies Nos. 99 & 101
Composers->Haydn->Symphonies Nos. 94 & 98
Composers->Haydn->Violin Concertos
Composers->Bach
Composers->Bach->Brandenburg Concertos Nos. 1 & 3
Composers->Bach->Violin Concertos
Composers->Beethoven
Composers->Beethoven->Symphony No. 7
Composers->Beethoven->Symphony No. 9
Composers->Beethoven->Symphony No. 5
Composers->Mozart
Composers->Mozart->Symphony No. 34
Composers->Mozart->Symphony in C, No. 41: Jupiter
Composers->Mozart->Concerto in D for Piano

The results of running System.out.println(getPathForFirstNodeWithRegex("Piano", tree2())); is:
Composers->Mozart->Concerto in D for Piano

Running clickNodeMatchingRegex(tree2(), "Piano"); against the same tree will expand the tree to the Composers->Mozart->Concerto in D for Piano node and click on it.

Useful, huh?

Here’s the code to do all that:

package Scratch;

import resources.Scratch.TreeManagerHelper;

/*
* Copyright (c) 2006, Nathaniel Ritmeyer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* – Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
* – Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* – Neither the name of natontesting.com nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

/*
* www.natontesting.com
*/

//fix up the following two lines of code
//to be correct for your project/class

import com.rational.test.ft.object.interfaces.GuiSubitemTestObject;
import com.rational.test.ft.vp.ITestDataTree;
import com.rational.test.ft.vp.ITestDataTreeNode;
import com.rational.test.ft.vp.impl.ObjectReference;
import com.rational.test.util.regex.Regex;

public class TreeManager extends TreeManagerHelper
{
public void testMain(Object[] args)
{
try
{
//System.out.println(getPathForFirstNodeWithRegex(“Piano”, tree2()));
//printTreeNavigationPaths(tree2());
//clickNodeWithPath(tree2(), “Composers->Mozart->Concerto in D for Piano”);
clickNodeMatchingRegex(tree2(), “Piano”);
}
catch(Exception e)
{
e.printStackTrace();
}
}

/**
* Returns the navigation string for the first node in the tree to
* match the regec
* @param sPattern –the mattern to match the node on
* @param targetTree –the tree to get the details from
* @return The first navigation string in the tree that matches the pattern
* @throws Exception
*/
public static String getPathForFirstNodeWithRegex(String sPattern, GuiSubitemTestObject targetTree) throws Exception
{
//create the regex object that will do the matching for us
Regex rPattern = new Regex(sPattern);

//create a string array to hold all the navigation strings
String myPaths[] = arrayOfNavigationPaths(targetTree);

//loop through each navigation string, starting from the top of the
//tree, and working to the bottom of the tree
for(int i = 0; i < myPaths.length; i++)
{
//if the regex matches the current node…
if(rPattern.matches(myPaths[i]))
{
//return the navigation string for that node
return myPaths[i];
}
}

//if we got here, nothing in the tree matched the regex. Return null
return null;
}

/**
* Clicks on a node in the tree
* @param targetTree –the tree to select the node from
* @param sNodePath –the path of the node
* @throws Exception
*/
public static void clickNodeWithPath(GuiSubitemTestObject targetTree, String sNodePath) throws Exception
{
targetTree.click(atPath(sNodePath));
}

/**
* Click on the first node that matches a regular expression
* @param targetTree –the tree to select the node from
* @param sRegex –the regex to identify the node with
* @throws Exception
*/
public static void clickNodeMatchingRegex(GuiSubitemTestObject targetTree, String sRegex) throws Exception
{
targetTree.click(atPath(getPathForFirstNodeWithRegex(sRegex, targetTree)));
}

/**
* Prints the tree navigation details of all nodes in a tree to the console
* @param targetTree –the tree to get the details from
* @throws Exception
*/
public static void printTreeNavigationPaths(GuiSubitemTestObject targetTree) throws Exception
{
//get the nodes from the tree
ITestDataTreeNode[] nodes = ((ITestDataTree)targetTree.getTestData(“tree”)).getTreeNodes().getRootNodes();

//print the navigation strings for those nodes
System.out.println(TreeManager.getPathForAllNodes(“”, nodes, true));
}

/**
* Returns a string array where each element is a navigation string.
* The array is ordered in the same way that the tree is ordered
* @param targetTree –the tree to get the details from
* @return –String[]
* @throws Exception
*/
private static String[] arrayOfNavigationPaths(GuiSubitemTestObject targetTree) throws Exception
{
//set up array to hold details
String sNavigationPaths[];

//get the nodes from the tree
ITestDataTreeNode[] nodes = ((ITestDataTree)targetTree.getTestData(“tree”)).getTreeNodes().getRootNodes();

//return a string array, based on splitting the results
//string on the newline character
return TreeManager.getPathForAllNodes(“”, nodes, true).split(“\n”);
}

/**
* Iterates through all nodes and figures out the tree navigation path for
* each node.
* @param sPrefix –the current location in the tree
* @param nNodes –the nodes to iterate through (generally, this is just the
* root node of the tree, although beginning halfway up the tree is possible)
* @param isRootNode –pass in “true” if the nNodes being passed in is the
* root node.
* @return — A string containing the navigation path for each node, separated
* by return characters
*/
private static String getPathForAllNodes(String sPrefix, ITestDataTreeNode[] nNodes, boolean isRootNode)
{
//if there are no nodes, return
if(nNodes == null)
{
return “”;
}

//prepare a blank string to contain the result of interogating the node
String sResult= “”;

//loop through each node
for (int index = 0; index < nNodes.length; index++)
{
//get the text value displayed on the node
ObjectReference or = (ObjectReference) nNodes[index].getNode();
String sNodeText = or.getObject().toString();

//decide whether to prefix the node with “->” or not
String sNextLine;
if(isRootNode)
{
//we’re at the root node, don’t prefix
sNextLine = sNodeText;
}
else
{
/*
* we’re not at the root node, we’re at some child somewhere
* prefix the node name with the tree nav so far, and also
* the “->” string…
*/
sNextLine = sPrefix + “->” + sNodeText;
}

//add the navigation line to the results
sResult = sResult + sNextLine + “\n”;

//get the child nodes of the current node
ITestDataTreeNode[] nChildren = nNodes[index].getChildren();

/*
* if the current node has children, recursively call this method,
* passing in the current tree nav path, the child nodes, and “false”
* so that we know that we’re not at the tree root any more
*/
if(nChildren != null)
{
sResult = sResult + getPathForAllNodes(sNextLine, nChildren, false);
}
}

//we’ve finished iterating through the tree; bail!
return sResult;
}
}
As always, please let me know of any improvements/additions you make!

Method to wait for correct number of rows in a table in RFT

I’ve previously put up code that can be used in RFT to wait for data to appear in a table. What follows is a similar method, but instead of waiting for data, it waits for an exact number of rows to be present in a table. It’s useful if you are expecting a row to disappear from a table after processing the row, or something like that…

To use the method, paste it into whatever class deals with tables (a class called something like “TableManager”), and then call the method statically passing in the table and the expected number of rows as parameters.

E.g.
TableManager.waitForParticularNumberOfRows(tblAccounts(), 4);

That line of code will make the test wait for the default waiting time (same as is used for waitForExistence), polling the tblAccounts table to see if it has 4 rows yet. If it does, the script continues. If by the end of the waiting period the row count still isn’t 4, an exception is thrown (again, just like waitForExistence).

/*
* Copyright (c) 2006, Nathaniel Ritmeyer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* – Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
* – Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* – Neither the name of natontesting.com nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* www.natontesting.com
*/
public static void waitForParticularNumberOfRows(GuiSubitemTestObject tblTargetTable, int iNumberOfRows) throws Exception
{
//get the waitForExistence values
Double dMaxWaitTime = (Double)getOption(IOptionName.MAXIMUM_WAIT_FOR_EXISTENCE);
Double dTimeBtwnRetry = (Double)getOption(IOptionName.WAIT_FOR_EXISTENCE_DELAY_BETWEEN_RETRIES);
int iMaxWaitForExistenceTime = dMaxWaitTime.intValue();
int iTimeToWaitBetweenRetries = dTimeBtwnRetry.intValue();

//work out how many times we’re going to check
int iNumberOfTimesToCheck = iMaxWaitForExistenceTime / iTimeToWaitBetweenRetries;

//loop iNumberOfTimesToCheck number of times checking for a particular
//number of rows
for(int iCheckCounter = 0; iCheckCounter < iNumberOfTimesToCheck; iCheckCounter++)
{
//get the contents of the table
ITestDataTable itdt = (ITestDataTable)tblTargetTable.getTestData(“contents”);

//if the number of rows doesn’t match what you want…
if(itdt.getRowCount() != iNumberOfRows)
{
//…sleep…
sleep(iTimeToWaitBetweenRetries);
}
else
{
//If we get here it’s because the table contains the particular
//number of rows that you’re after…
//It’s time to escape!
return;
}
}

throw new Exception(“Timed out waiting for correct number of rows”);
}
As always, any improvements are welcome!

Artificial constraint on object names lifted

In RFT, the default setting when associating a mapped test object to a test script is to truncate the object name to 30 characters. With a naming convention that often takes object names past this length, I regularly have to correct the object name using the Renew Name in Script option. After a while this becomes *very* tedious. If you don’t know what I’m talking about, create a public test object map, associate it with a new test script, add an object to the map and give it a name that is more than 30 characters long. Now associate that object with the test script, and you’ll see in Script Explorer that the name has been truncated to 30 characters. Imagine having to fix that 4,000 times over…

A few weeks ago, I asked a question on the RFT discussion forum titled: “Character limit on Add Object to Script”. Unfortunately, I got no replies. In answer to another question was a clue… something about “rt.max_identifier_length” and the fact that it could be set in a properties file somewhere.

Our team set about hunting for the value, and we found it. It was buried in an XML configuration file called “rational_ft.rftcust”. Here’s how to change the default of 30 characters to the maximum allowed of 128:

1) Quit all IBM products (that includes things like Lotus Notes!) (Reboot if necessary)

2) Open the following file: “C:\Program Files\IBM\Rational\SDP\6.0\FunctionalTester\eclipse\plugins\com.rational.test.ft.wswplugin_6.1.0\rational_ft.rftcust”

3) Search for “rt.max_identifier_length”
Change the “DefaultValue” value to 128

4) Save

5) Open RFT and try associating a test object with a 31+ character name with a test script, and behold the magic!

RFT Object Roles, Class and TestData Types

I’ve been putting together a table that brings together the following info:

Column 1. Object Type – this comes from the Test Object Map Icons page in the RFT help system. The page lists all of the objects that RFT knows about, displays the icon that RFT assigns to a mapped object of that kind, and a human-friendly name for the object type
Column 2. RFT Role – this is what is displayed against the Role field under the Administrative tab in the Object Map window. Running the getTestData method will return this string
Column 3. Test Object Class – The class that RFT instantiates to deal with the mapped object
Column 4. Test Data Types – These are the valid string values that can be passed in to the getTestData method
Column 5. Description – A description of the type of data that is returned
Column 6. Data Class – The class of the object that is returned. Note that these classes are the classes that RFT use for their VP (verification point) functionality

I hope you find it a useful reference. I’ll improve it as we start putting it to heavy use. Also, you’ll notice a fair number of gaps. Everywhere you see ??? is where I could do with some input. I can’t find objects of those types, so I can’t get the data I need to fill in the table. Any help is appreciated.

  Administrative Details Interface Summary
Object Type RFT Role Test Object Class Test Data Types Description Data Class
Applet Applet GuiTestObject n/a n/a n/a
Browser Browser BrowserTestObject n/a n/a n/a
Button Button ToggleGUITestObject state Toggle Button State ITestData
Button Button ToggleGUITestObject text Button Visible Text ITestDataText
Calendar ??? ??? ??? ??? ???
Canvas ??? ??? ??? ??? ???
Check box CheckBox ToggleGUITestObject state CheckBox Button State ITestData
Check box CheckBox ToggleGUITestObject text CheckBox Visible Text ITestDataText
Color chooser ??? ??? ??? ??? ???
Combo box ComboBox TextSelectGuiSubitemTestObject list List Elements ITestDataList
Combo box ComboBox TextSelectGuiSubitemTestObject selected Selected List Elements ITestDataText
Combo box ComboBox TextSelectGuiSubitemTestObject text Current Text ITestDataText
Combo list box ??? ??? ??? ??? ???
Date/time picker ??? ??? ??? ??? ???
Dialog Dialog TopLevelTestObject n/a n/a n/a
Document Document GuiTestObject text Visible Text ITestDataText
File chooser ??? ??? ??? ??? ???
Filler ??? ??? ??? ??? ???
Form ??? ??? ??? ??? ???
Frame Frame TopLevelTestObject state Selected State n/a
Generic ??? ??? ??? ??? ???
Grid ??? ??? ??? ??? ???
Group box ??? ??? ??? ??? ???
Horizontal scroll bar ??? ??? ??? ??? ???
HTML component Html GuiTestObject text Visible Text ITestDataText
Image Image StatelessGuiSubitemTestObject text Visible Text ITestDataText
Internal frame InternalFrame InternalFrameTestObject n/a n/a n/a
Java Jfc GuiTestObject n/a n/a n/a
Label Label GuiTestObject icontext Label Icon Description ITestDataText
Label Label GuiTestObject text Label Visible Text ITestDataText
Link Link GuiTestObject text Visible Text ITestDataText
List List SelectGuiSubitemTestObject list List Elements ITestDataList
List List SelectGuiSubitemTestObject selected Selected List Elements ITestDataList
Menu Menu ToggleGUITestObject extendedMenu Menu Hierarchy with Properties ITestDataTree
Menu Menu ToggleGUITestObject menu Menu Hierarchy ITestDataTree
Menu Menu ToggleGUITestObject text Button Visible Text ITestDataText
Menu bar MenuBar GuiSubitemTestObject extendedMenu Menu Hierarchy with Properties ITestDataTree
Menu bar MenuBar GuiSubitemTestObject menu Menu Hierarchy ITestDataTree
Menu item MenuItem ToggleGUITestObject text Button Visible Text ITestDataText
Page tab TabbedPage GuiTestObject n/a n/a n/a
Page tab list PageTabList GuiSubitemTestObject list List Elements ITestDataList
Page tab list PageTabList GuiSubitemTestObject selected Selected Tab Element ITestDataList
Panel Panel GuiTestObject n/a n/a n/a
Pop-up menu PopupMenu GuiSubitemTestObject extendedMenu Menu Hierarchy with Properties ITestDataTree
Pop-up menu PopupMenu GuiSubitemTestObject menu Menu Hierarchy ITestDataTree
Progress bar ??? ??? ??? ??? ???
Radio button RadioButton ToggleGUITestObject state Toggle Button State ITestData
Radio button RadioButton ToggleGUITestObject text Button Visible Text ITestDataText
Scroll bar ??? ??? ??? ??? ???
Scroll pane ScrollPane GuiSubitemTestObject n/a n/a n/a
Separator ??? ??? ??? ??? ???
Slider ??? ??? ??? ??? ???
Split pane SplitPane GuiSubitemTestObject n/a n/a n/a
Status bar ??? ??? ??? ??? ???
Tabbed page TabbedPage GuiTestObject n/a n/a n/a
Table Table GuiSubitemTestObject contents Table Contents ITestDataTable
Table Table GuiSubitemTestObject selected Selected Table Cells ITestDataTable
Table header TableHeader GuiSubitemTestObject TableHeader TableHeader Names ITestDataList
Text Text TextGuiSubitemTestObject selected Selected Text ITestDataText
Text Text TextGuiSubitemTestObject text Visible Text ITestDataText
Toggle button ??? ??? ??? ??? ???
Tool tip ??? ??? ??? ??? ???
Toolbar ??? ??? ??? ??? ???
Tree Tree GuiSubitemTestObject selected selected tree Hierarchy ITestDataTree
Tree Tree GuiSubitemTestObject tree tree Hierarchy ITestDataTree
Up/Down control ??? ??? ??? ??? ???
Window ??? ??? ??? ??? ???