ObjectManager 1.0

What follows is version 1.0 of what I’m currently calling “ObjectManager”. Although the name clashes with one of Rational Functional Tester’s (RFT) classes, it’ll do for now. If you can think of something better, drop me a line, or leave a comment. Another thing before we start, please note that the ObjectManager code is licensed under the BSD License so you don’t *need* to let me know of the changes you make to the code, but I really would appreciate it and due credit will be given as I add your changes to the code.

What ObjectManager does is allow the following in your code:

ObjectManager om = new ObjectManager();
om.runThis("myAppLogonTxtUserName", "setText", "bob");
om.runThis("myAppLogonTxtPassword", "setText", "s33cr1t");
om.runThis("myAppLogonBtnLogin", "click");
om.runThis("myAppWelcomeWndMain", "waitForExistence");

String sCurrentTimeAsDisplayedByAUT;
sCurrentTimeAsDisplayedByAUT = om.runThis(“myAppWelcomeLblCurrentTime”, “getText”).toString();
Basically, you can pass an object name as a string, and a method name as a string. Arguments can be passed as any type of object (String, Integer, etc), as an array of objects (the array should be predefined), or don’t need to be passed at all.

What’s the advantage of this? Well, not much if you are only doing record/playback style test automation. If you are building a framework of some description, you may find it useful. It is the most dynamic way of dealing with mapped test objects in RFT that I know of.

How does it work? It makes *heavy* use of java’s Reflections functionality. If you want more detail, have a look at the code. There’s more comments than code…

Is it finished? Well, it does what it says on the tin (…there is no tin…), but it could do with better handling of exceptions. I’ll be working on it and hopefully I’ll update it over the next few days. Any input is welcome!

How to use it?

  1. Create an “RFT script” class in your project called “ObjectManager”
  2. Copy the following code into the new file
  3. Fix up the line that defines the package location
  4. Fix up the line that points to the helper file
  5. Map all the objects you want to use (this may be a massive effort, it has been for me) in either the private test object map (discouraged), or a public/standalone test object map that is linked to the ObjectManager class
  6. Figure out how ObjectManager is going to fit into your framework
  7. Make the appropriate “runThis” calls wherever test object interaction is required.

If you can’t figure out why ObjectManager is so cool (though I say it myself), don’t worry about it. There are some very obvious ways that it can be used and extended, I’d be interested in your results!


/*
* 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
*/

//change the following line to point to the proper package location
package Scratch;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;

//change the following line to point to the correct helper file
import resources.Scratch.ObjectManagerHelper;

import com.rational.test.ft.object.interfaces.GuiTestObject;
import com.rational.test.ft.object.interfaces.TestObject;
import com.rational.test.ft.object.map.SpyMappedTestObject;

/**
* This class is designed to allow dynamic use of an object map. The main feature is
* the runThis(ObjectName, Method, Arguments) method. It takes in the ObjectName, the
* Method as strings, and the Arguments as an array of objects. Using reflection, the
* method creates an instance of the mapped object, and runs the method against it,
* with the arguments provided.
*
* The mapped objects should be in this classes helper file, preferably by the use of
* a public Test Object Map.
*
* Other methods have been provided that will help when going through the initial
* object mapping trauma. The “countAllMappedTestObjects” method provides a count of
* all of the currently mapped objects in this class’ helper file. Useful it you’re a
* stats junkie like me. The “printAllMappedTestObjects” method will print a list of
* all the object names to the console. Useful if you’re going to export the list to
* a text file, database, spreadsheet, etc…
*/
public class ObjectManager extends ObjectManagerHelper
{
public void testMain(Object args[])
{
//countAllMappedTestObjects();
//printAllMappedTestObjects();
}

/**
* Saves hassle if the method doesn’t take any arguments
*
* @param sObjectName –the exact name of the RFT Mapped Object you want to use
* @param sMethod –the exact name of the method you want to run against the object
* @param oArg –the argument to the method to run against the object
* @return Object –this will be whatever the method “sMethod” returns
* @throws InvocationTargetException –the method you wanted to call has thrown an exception
* @throws Exception –this could be any of the exception types below – catch
* these, they’ll let you know what went wrong, if anything.
*/
public Object runThis(String sObjectName, String sMethod) throws Exception, InvocationTargetException
{
return runThis(sObjectName, sMethod, null);
}

/**
* Saves hassle if the method needs only one argument instead of
* an array of them.
*
* @param sObjectName –the exact name of the RFT Mapped Object you want to use
* @param sMethod –the exact name of the method you want to run against the object
* @param oArg –the argument to the method to run against the object
* @return Object –this will be whatever the method “sMethod” returns
* @throws InvocationTargetException –the method you wanted to call has thrown an exception
* @throws Exception –this could be any of the exception types below – catch
* these, they’ll let you know what went wrong, if anything.
*/
public Object runThis(String sObjectName, String sMethod, Object oArg) throws Exception, InvocationTargetException
{
Object myObjectArgs[] = new Object[1];

myObjectArgs[0] = oArg;

return runThis(sObjectName, sMethod, myObjectArgs);
}

/**
* Runs a method against an object using the arguments passed in.
*
* @param sObjectName –the exact name of the RFT Mapped Object you want to use
* @param sMethod –the exact name of the method you want to run against the object
* @param sArgs –the arguments to the method to run against the object
* @return Object –this will be whatever the method “sMethod” returns
* @throws InvocationTargetException –the method you wanted to call has thrown an exception
* @throws Exception –this could be any of the exception types below – catch
* these, they’ll let you know what went wrong, if anything.
*/
public Object runThis(String sObjectName, String sMethod, Object sArgs[]) throws Exception, InvocationTargetException
{
/////////////////////////////////////////////////////////////////////////////
//////////////////////// Initial Rational Stuff /////////////////////////
/////////////////////////////////////////////////////////////////////////////

//get a reference to the desired object in the object map
SpyMappedTestObject smto = getMappedTestObject(sObjectName);

/////////////////////////////////////////////////////////////////////////////
/////////////////////////// Class Discovery /////////////////////////////
/////////////////////////////////////////////////////////////////////////////

//get the class of the above object reference
String sRFTClassForAUTObject = smto.getTestObjectClassName();

//get the class of the object referenced by the ‘smto’ object
Class cRFTObjectClass;

try
{
cRFTObjectClass = Class.forName(“com.rational.test.ft.object.interfaces.” + sRFTClassForAUTObject);
}
catch(ClassNotFoundException cnfe)
{
throw(cnfe);
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////// Constructor Setup ///////////////////////////
/////////////////////////////////////////////////////////////////////////////

//set up an object to reference the constructor method of the cRFTObjectClass
Constructor cnRFTObjectClassConstructor;

//since it is possible to have more than one constructor, you need to specify
//which one you want. Constructors are differentiated based on the parameters
//passed to them.
//We need to set up a class array that matches what the RFTClass expects. In
//this instance, that is just the “smto” object, so the array we set up has
//length of 1 containing only the “SpyMappedTestObject” class type.
Class cnConstructorArgs[] = new Class[1];
cnConstructorArgs[0] = SpyMappedTestObject.class;

//now that we have that class array, we can “get” the constructor
try
{
cnRFTObjectClassConstructor = cRFTObjectClass.getConstructor(cnConstructorArgs);
}
catch(NoSuchMethodException nsme)
{
throw(nsme);
}

//We are getting close to being able to run the constructor… we just need to
//put the arguments to the constructor into an array… once we’ve done that,
//we’re done…
SpyMappedTestObject smtoArray[] = new SpyMappedTestObject[1];
smtoArray[0] = smto;

//Done. We can now run the constructor with the arguments we just created
Object oActualRFTObject;

try
{
oActualRFTObject = cnRFTObjectClassConstructor.newInstance(smtoArray);
}
catch(InvocationTargetException ite)
{
throw(ite);
}
catch(IllegalAccessException iae)
{
throw(iae);
}
catch(InstantiationException ie)
{
throw(ie);
}

/////////////////////////////////////////////////////////////////////////////
////////////////////// Method Setup and Execution ///////////////////////
/////////////////////////////////////////////////////////////////////////////

//We now need to query the class to see if it contains a method that matches
//the one we want to run. To do that, we need to set up a class array containing
//a list of classes in the same order as the ones we want the method to accept
Class cArgType[];

if(sArgs == null)
{
//if no args got passed in, create an empty array
cArgType = new Class[0];
}
else
{
cArgType = new Class[sArgs.length];

//we use this magic ‘for’ loop to create the class array.
for(int iLoopCounter = 0; iLoopCounter < sArgs.length; iLoopCounter++)
{
//To check the type of the object and create an object instance for method
cArgType[iLoopCounter] = getCorrectClassForName(sArgs[iLoopCounter].getClass().getName());
}
}

//Create the reference to the method we want to run
Method mMethodToRunAgainstActualObject;

//get the method, based on its name and the argument types
try
{
mMethodToRunAgainstActualObject = cRFTObjectClass.getMethod(sMethod, cArgType);
}
catch(NoSuchMethodException nsme)
{
/*
* You’ll end up here if the method you want to execute doesn’t exist.
* Need to do more here. Check www.natontesting.com for the latest version.
*/
throw(nsme);
}

//set up an object to hold the return from the method
Object oReturnFromMethod = null;

//run the method!
try
{
oReturnFromMethod = mMethodToRunAgainstActualObject.invoke(oActualRFTObject, sArgs);
}
catch(InvocationTargetException ite)
{
/*
* If we get here, it means that whatever method was run threw an exception. We
* need to capture this.
* Eg: ObjectNotFoundException will arrive here…
* Need to do more here. Check www.natontesting.com for the latest version.
*/
throw(ite);
}
catch(IllegalAccessException iae)
{
/*
* If you try to call a private method, it’ll fail and you’ll end
* up here, and you’ll look really stupid.
* Need to do more here. Check www.natontesting.com for the latest version.
*/
throw(iae);
}
catch(IllegalArgumentException iae)
{
/*
* The aguments you passed to the method were somehow wrong
* Need to do more here. Check www.natontesting.com for the latest version.
*/
throw(iae);
}
catch(Exception e)
{
throw(e);
}

//put away your toys after playing with them…
unregisterAll();

return oReturnFromMethod;
}

/**
* Prints a count of the test objects to the console
*/
public void countAllMappedTestObjects()
{
Enumeration e = getAllMappedTestObjects();
long lCount = 0;

while(e.hasMoreElements())
{
lCount++;
e.nextElement();
}

System.out.println(“Number of Objects: ” + lCount);
}

/**
* Prints all the mapped test objects to the console
*/
public void printAllMappedTestObjects()
{
Enumeration e = getAllMappedTestObjects();

while(e.hasMoreElements())
{
System.out.println(e.nextElement());
}
}

/**
* Returns an enumeration containing the names of all of the mapped objects
* @return Enumeration
*/
private Enumeration getAllMappedTestObjects()
{
return this.getScriptDefinition().getTestObjectNames();
}

/**
* Returns a class object based on the sClassName parameter, corrected
* for primitive types
* @param sClassName –the name of the candidate class
* @return a class object
* @throws Exception
*/
private Class getCorrectClassForName(String sClassName) throws Exception
{
//We’ll hold the name of the correct class in here
String sClassToCreate = “”;

/*
* The following if/else stuff will check to see if the candidate
* class is one that represents a primitive type. If it is, set the
* class to return to be the corresponding primitive. Otherwise
* set the class to return as the original type
*/
if(sClassName.compareTo(“java.lang.Boolean”) == 0)
{
return boolean.class;
}
else if(sClassName.compareTo(“java.lang.Character”) == 0)
{
return char.class;
}
else if(sClassName.compareTo(“java.lang.Byte”) == 0)
{
return byte.class;
}
else if(sClassName.compareTo(“java.lang.Short”) == 0)
{
return short.class;
}
else if(sClassName.compareTo(“java.lang.Integer”) == 0)
{
return int.class;
}
else if(sClassName.compareTo(“java.lang.Long”) == 0)
{
return long.class;
}
else if(sClassName.compareTo(“java.lang.Float”) == 0)
{
return float.class;
}
else if(sClassName.compareTo(“java.lang.Double”) == 0)
{
return double.class;
}
else
{
return Class.forName(sClassName); //original class type
}
}
}

Method to wait for data to appear in an RFT table

It is often the case that running the waitForExistence method against a table is not enough. Sometimes you need to wait for data to appear in a table and waitForExistence won’t give you that. What is required is a method that will work the same way as waitForExistence but instead waits for data to appear in the table. What follows is a method called waitForData which will do exactly that! The method uses the same timeouts as the waitForExistence method; it gets the parameters dynamically, according to what you have set in your preferences.

The code is quite heavily commented so you can see exactly what it is doing. To use the method, copy it into a class that deals with Tables (or the relevant place in your framework) and call the method from wherever you deal with tables. The method takes the table object as a parameter, so if your table is called tblAccounts and the class you’ve pasted the method into is called TableManager, then you’d use it like this:

TableManager tm = new TableManager();
tm.waitForData(tblAccounts());

Without further ado, here’s the code:


/*
* 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 void waitForData(GuiSubitemTestObject gsito) throws Exception
{
/*
* first of all, we’ll wait for the table object.
* We’ll worry about the data later on…
*/
try
{
gsito.waitForExistence();
}
catch(ObjectNotFoundException onfe)
{
throw new Exception(“Couldn’t find the table”, onfe);
}

/*
* If we’ve arrived here, it’s because the table object exists.
* We can now start waiting for the data
*/

/*
* This method uses the default wait for existence time set in your preferences. If you
* change the values in your preferences, this method will scale with your changes.
*/

//Get default times, stage 1 – get the double values
Double dMaxWaitTime = (Double)getOption(IOptionName.MAXIMUM_WAIT_FOR_EXISTENCE);
Double dTimeBtwnRetry = (Double)getOption(IOptionName.WAIT_FOR_EXISTENCE_DELAY_BETWEEN_RETRIES);

//Get default times, stage 2 – get the int values from the double values
int iMaxWaitForExistenceTime = dMaxWaitTime.intValue();
int iTimeToWaitBetweenRetries = dTimeBtwnRetry.intValue();

/*
* Because the default amount of time between retries is 2 seconds, and the total
* amount of time to wait is 120 seonds, the object is only polled 60 (120/2) times.
* To keep this method in line with the rest of RFT’s methods that use the
* waitForExistence times, we should follow the same convention. The following int
* variable stores the number of times that we’re going to poll the object.
*/
int iNumberOfTimesToCheck = iMaxWaitForExistenceTime / iTimeToWaitBetweenRetries;

/*
* The following for loop performs the actual waitForData logic. Note that the
* time that it will take to run will be close but on t exactly the same length
* of time that the iMaxWaitForExistenceTime variable would have you believe. This
* is there are other operations happening apart from sleep which also take time.
* The difference between actual time and iMaxWaitForExistenceTime is negligible.
*/
for(int iCheckCounter = 0; iCheckCounter < iNumberOfTimesToCheck; iCheckCounter++)
{
//get the contents of the table
ITestDataTable itdt = (ITestDataTable)gsito.getTestData(“contents”);

//if there are 0 rows…
if(itdt.getRowCount() < 1)
{
//…sleep…
sleep(iTimeToWaitBetweenRetries);
}
else
{
//If we get here it’s because there was at least one row of data.
//It’s time to escape!
return;
}
}

/*
* If we arrive here, we’ve timed out whilst waiting for data to be
* displayed so we need to report an error
*/
throw new Exception(“Timed out waiting for table data”);
}

Example Naming Standard for Mapped AUT Objects

The most tedious part of creating a test automation framework in Rational Functional Tester (RFT) is mapping the objects that belong to the Application Under Test (AUT). There isn’t too much that can be done to aleviate the pain, your only hope is to make sure that you only have to map those objects once. One aspect of the object map that can be tamed is the naming of the objects. Using a naming standard consistently can increase the maintainability of the object map, so to save you figuring one out, here’s one that’s worked for me in the past.

Note 1: The naming convention is based on the “hierarchical name space” arrangement, similar to the way libraries are organised in java e.g. java.lang.String.
Note 2: The convention also uses “lowerCamelCase” to name the objects. Camel case is the practice of capitalising each word in a phrase, and concatenating the words by removing the spaces. “Lower” camel case is where the first letter of the phrase is changed to a lower case letter. Due to a quirk in RFT’s implementation of object mapping, “UpperCamelCase” is painful to use.
Note 3: No part of the naming standard is mandatory, but I’ve found through experience that the more of the convention is used, the more maintainable the object map is. In frameworks where there is only one object map, using the naming convention in its entirety is strongly advised. If your framework separates object maps by application, part 1 may not be necessary. If you have one object map for each window in your AUT, only the last 2 parts may be necessary.

Part 1
The name of each object begins with the name of the application or something that would identifiy the same. For example, if your AUT is called “Widget”, the name of each object that belongs to that app would begin with widget. Or if your AUT is called “Cheese Factory Management System”, beginning each relevant object with “cfms” would be enough. Beginning each object name with the name of the AUT ensures that they will be sorted correctly in an object map, i.e. all the objects for each AUT will be grouped together.

Part 2
The second section of the object name should define which section of the AUT it is in. The details of this will depend on the application you’re testing. If the AUT is made up of multiple windows, it may be logical to group together the objects that are located in a particular window. If the AUT is made up of one window with activity-related panels, you could use the panel names. If you’re testing a web app, it may be logical to group together all the objects on one page. The AUT in question will be the deciding factor on what this section of the object name will be. A window-based application makes deciding on the name easy; other styles of AUT layout could make this more difficult.

Example 1: Each object in the “Logon” window of the “Widget” AUT could begin with widgetLogon, or msdgfwLogon.
Example 2: Each object in the “Customer Name & Address Details” window of the “Cheese Factory Management System” could begin with cfmsCustNameAddressDetails.

Part 3
Use of the third part of the naming convention is not mandatory, but is useful for mapping a window within the AUT that contains many objects. Objects in windows are usually grouped together based on function. For example, a window containing both Name and Address details may split the relevant objects into separate groups. Deciding on a name for the window area is usually made quite easy when the objects are grouped into a frame; you can just use the name given by the AUT. If the group of objects don’t have a frame that they belong in, a name for the group of them should be carefully chosen. Even without a frame, getting a name for a group of objects can still be easy, e.g. all objects in a tab can use the tab name; objects that define search criteria can use Search, etc…

Example: Each customer name related object in the “Customer Name & Address Details” window of the “Cheese Factory Management System” could begin with cfmsCustNameAddressDetailsName; the customer address related objects could begin with cfmsCustNameAddressDetailsAddress.

Part 4
Now that all objects in an AUT are grouped down to a specific location there remains only the need to differentiate between the objects within windows (part 2), frames or tabs (part 3). The fourth section of the naming standard is used to identify what type of object the mapped object is; e.g. button, label, textfield, menu, window, etc… The following list of object types is given as a guide.

ObjectType Abbreviation
Button Btn
CheckBox Chk
Combo Box Cmb
Dialog Box Dlg
Editor Pane Edp
Label Lbl
List Lst
Option Button Opt
Picture Pct
Popup Menu Pop
Scroll Pane Scr
Tab Tab
Tabbed Pane Tpn
Table Tbl
Table Header Tbh
Text Field Txt
Tree Tre
Window Wnd
Defining the type of object in the naming convention leads to even more grouping together ob objects in RFT Script explorer. For example, all buttons in a particualr area of a particular window will be grouped together; or if part 3 of the naming convention wasn’t used, all objects of the same type within a window will be grouped together.

Example 1: All text fields in the window area to do with customer names in the “Customer Name & Address Details” window of the “Cheese Factory Management System” could begin with cfmsCustNameAddressDetailsNameTxt; the text fields in the
window area to do with address details could begin with cfmsCustNameAddressDetailsAddressTxt.

Part 5
The last part of the naming convetion is to identify the object itself. This is usually quite easy as GUI objects usually provide a name; e.g. a Save button could be called “Save”! A textfield labelled as “First Name” could be identified as “FirstName”.

Example 1: The text field for the first name of a customer in the “Customer Name & Address Details” window of the “Cheese Factory Management System” could be cfmsCustNameAddressDetailsNameTxtFirstName and the Last Name textfield could be cfmsCustNameAddressDetailsNameTxtLastName.

The naming convention is quite verbose, but it does provide a very maintainable object map. Name collisions are rare (I’ve never encountered any using the above convention), and due to the nature of the way us humans read and sort globs of text, the object names are actually quite readable!

Calculating Dates

So many things in applications are date specific. Make a booking for 10 days in the future; what is the date going to be in 8 months time; close this account in 5 years time; etc… Dealing with dates can be quite painful, and RFT being Java-based, it is made even more painful. The way java handles dates is very confusing so here’s something to help you get started. The following class provides methods for giving the current date, the date in n days, months or years (past and future). To use it just copy it into a new class (java class, not RFT class) called DateManager and fix up the package line.

/*
 * 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.
 *
 */

//set the following package path to the correct value
package Scratch;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateManager {

    SimpleDateFormat dateFormat; //set the value for this in the constructor to define what date format to return...

    public static void main(String args[]) throws Exception
    {
        DateManager dm = new DateManager();
    }

    /**
     * Sets up a new DateManager, and defines the date format to be used
     * @throws Exception
     */
    public DateManager() throws Exception
    {
        dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        //See the following for the formats: http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html

	/*
        System.out.println("Current Date: " + getCurrentDate());
        System.out.println("Date in 1 day: " + dateInNYearsTime(1));
        System.out.println("Date in 10 days: " + dateInNYearsTime(10));
        System.out.println("Date in 200 days: " + dateInNYearsTime(200));
        System.out.println("Date in 1000 days: " + dateInNYearsTime(1000));
	 */
    }

    /**
     * Calculates the current date and returns it as a string in the format defined above
     * @return --a string containing today's date
     */
    public String getCurrentDate()
    {
        Date myDate = new Date();
        return dateFormat.format(myDate);
    }

    /**
     * Returns a date modified by the iDays parameter relative to the current date
     * @param sDays --string value of how many days to add/subtract from the current date
     * @return --a string value of the calculated date
     * @throws Exception
     */
    public String dateInNDaysTime(int iDays) throws Exception
    {
        Calendar cMyCalendar = Calendar.getInstance();
        cMyCalendar.add(Calendar.DATE, iDays);
        return dateFormat.format(cMyCalendar.getTime());
    }

    /**
     * Returns a date modified by the iMonths parameter relative to the current date
     * @param sMonths --string value of how many months to add/subtract from the current date
     * @return --a string value of the calculated date
     * @throws Exception
     */
    public String dateInNMonthsTime(int iMonths) throws Exception
    {
        Calendar cMyCalendar = Calendar.getInstance();
        cMyCalendar.add(Calendar.MONTH, iMonths);
        return dateFormat.format(cMyCalendar.getTime());
    }

    /**
     * Returns a date modified by the iYears parameter relative to the current date
     * @param sYears --string value of how many years to add/subtract from the current date
     * @return --a string value of the calculated date
     * @throws Exception
     */
    public String dateInNYearsTime(int iYears) throws Exception
    {
        Calendar cMyCalendar = Calendar.getInstance();
        cMyCalendar.add(Calendar.YEAR, iYears);
        return dateFormat.format(cMyCalendar.getTime());
    }
}

Method to Start Applications

Here’s a method that can be used to start configured applications in RFT. I guess asking “What’s the big deal” is a fair question… Well, this method will take in any string and run the associated app. If the app isn’t there, the script won’t just die (like I’ve seen done at a number of places), but will inform the user that there is no configured AUT by that name, followed by a list of configured applications. It’s small stuff like this that will save you hours of hassle.

/*
* 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.
*
*/
public void startThisApp(String sAppName)
{
    try
    {
        startApp(sAppName);
    }
    catch(RunException re)
    {
        String sAppList[] = getApplications();

        if(sAppList.length < 1)
        {
            System.out.println("You don't have any apps configured! Before you run your app, you need to configure RFT to be able to run it");
        }
        else
        {
            System.out.println("Looks like that app doesn't exist. Here's a list of ones that do: ");
            for(int iNumberOfConfiguredApps = 0; iNumberOfConfiguredApps < sAppList.length; iNumberOfConfiguredApps++)
            {
                System.out.println(sAppList[iNumberOfConfiguredApps]);
            }
        }
    }
}

List of RFT Object Properties and their Class

Using the Object Properties method mentioned elsewhere, I’ve put together the following (probably incomplete) table of Rational Functional Tester Object properties and their class. The list is a big time saver. Sorry about the layout, it could be better. Much better. I was rushed.

TopLevelTestObject
height java.lang.Integer
displayable java.lang.Boolean
undecorated java.lang.Boolean
focusOwner java.lang.Boolean
focusTraversalPolicySet java.lang.Boolean
defaultCloseOperation java.lang.Integer
fontSet java.lang.Boolean
focusTraversable java.lang.Boolean
focus java.lang.Boolean
foreground java.awt.Color
focusTraversalKeysEnabled java.lang.Boolean
focusCycleRoot java.lang.Boolean
alignmentY java.lang.Float
alignmentX java.lang.Float
cursorSet java.lang.Boolean
width java.lang.Integer
lightweight java.lang.Boolean
backgroundSet java.lang.Boolean
name java.lang.String
location java.awt.Point
bounds java.awt.Rectangle
focused java.lang.Boolean
minimumSize java.awt.Dimension
maximumSize java.awt.Dimension
class java.lang.String
title java.lang.String
state java.lang.Integer
visible java.lang.Boolean
font com.rational.test.ft.value.FontInfo
extendedState java.lang.Integer
valid java.lang.Boolean
componentCount java.lang.Integer
background java.awt.Color
focusable java.lang.Boolean
active java.lang.Boolean
opaque java.lang.Boolean
focusableWindow java.lang.Boolean
size java.awt.Dimension
showing java.lang.Boolean
doubleBuffered java.lang.Boolean
warningString java.lang.String
ignoreRepaint java.lang.Boolean
resizable java.lang.Boolean
y java.lang.Integer
x java.lang.Integer
cursorType java.lang.Integer
foregroundSet java.lang.Boolean
enabled java.lang.Boolean
preferredSize java.awt.Dimension
maximizedBounds java.lang.String
focusableWindowState java.lang.Boolean
locationOnScreen java.awt.Point
GuiTestObject
y java.lang.Integer
focusable java.lang.Boolean
x java.lang.Integer
foreground java.awt.Color
visibleRect java.awt.Rectangle
fontSet java.lang.Boolean
bounds java.awt.Rectangle
focusOwner java.lang.Boolean
displayable java.lang.Boolean
toolTipText java.lang.String
preferredSize java.awt.Dimension
text java.lang.String
visible java.lang.Boolean
horizontalAlignment java.lang.Integer
lightweight java.lang.Boolean
height java.lang.Integer
horizontalTextPosition java.lang.Integer
managingFocus java.lang.Boolean
font com.rational.test.ft.value.FontInfo
focusTraversable java.lang.Boolean
verticalAlignment java.lang.Integer
paintingTile java.lang.Boolean
displayedMnemonicIndex java.lang.Integer
width java.lang.Integer
class java.lang.String
name java.lang.String
optimizedDrawingEnabled java.lang.Boolean
focusCycleRoot java.lang.Boolean
verifyInputWhenFocusTarget java.lang.Boolean
showing java.lang.Boolean
maximumSize java.awt.Dimension
backgroundSet java.lang.Boolean
autoscrolls java.lang.Boolean
displayedMnemonic java.lang.Integer
ignoreRepaint java.lang.Boolean
minimumSize java.awt.Dimension
cursorSet java.lang.Boolean
validateRoot java.lang.Boolean
maximumSizeSet java.lang.Boolean
uIClassID java.lang.String
locationOnScreen java.awt.Point
debugGraphicsOptions java.lang.Integer
location java.awt.Point
size java.awt.Dimension
valid java.lang.Boolean
componentCount java.lang.Integer
iconTextGap java.lang.Integer
minimumSizeSet java.lang.Boolean
requestFocusEnabled java.lang.Boolean
enabled java.lang.Boolean
alignmentY java.lang.Float
alignmentX java.lang.Float
preferredSizeSet java.lang.Boolean
focus java.lang.Boolean
background java.awt.Color
opaque java.lang.Boolean
focusTraversalPolicySet java.lang.Boolean
foregroundSet java.lang.Boolean
verticalTextPosition java.lang.Integer
focusTraversalKeysEnabled java.lang.Boolean
doubleBuffered java.lang.Boolean
GuiTestObject
foregroundSet java.lang.Boolean
visible java.lang.Boolean
managingFocus java.lang.Boolean
actionCommand java.lang.String
componentCount java.lang.Integer
width java.lang.Integer
foreground java.awt.Color
focusable java.lang.Boolean
y java.lang.Integer
x java.lang.Integer
focusTraversable java.lang.Boolean
class java.lang.String
contentAreaFilled java.lang.Boolean
preferredSizeSet java.lang.Boolean
enabled java.lang.Boolean
borderPainted java.lang.Boolean
ignoreRepaint java.lang.Boolean
debugGraphicsOptions java.lang.Integer
text java.lang.String
height java.lang.Integer
minimumSizeSet java.lang.Boolean
focusPainted java.lang.Boolean
optimizedDrawingEnabled java.lang.Boolean
defaultCapable java.lang.Boolean
validateRoot java.lang.Boolean
verticalAlignment java.lang.Integer
displayedMnemonicIndex java.lang.Integer
size java.awt.Dimension
bounds java.awt.Rectangle
horizontalTextPosition java.lang.Integer
lightweight java.lang.Boolean
fontSet java.lang.Boolean
label java.lang.String
backgroundSet java.lang.Boolean
displayable java.lang.Boolean
verifyInputWhenFocusTarget java.lang.Boolean
visibleRect java.awt.Rectangle
location java.awt.Point
focusTraversalKeysEnabled java.lang.Boolean
valid java.lang.Boolean
showing java.lang.Boolean
cursorSet java.lang.Boolean
defaultButton java.lang.Boolean
name java.lang.String
autoscrolls java.lang.Boolean
focusOwner java.lang.Boolean
focusTraversalPolicySet java.lang.Boolean
preferredSize java.awt.Dimension
minimumSize java.awt.Dimension
rolloverEnabled java.lang.Boolean
mnemonic java.lang.Integer
focusCycleRoot java.lang.Boolean
multiClickThreshhold java.lang.Long
focus java.lang.Boolean
horizontalAlignment java.lang.Integer
background java.awt.Color
uIClassID java.lang.String
iconTextGap java.lang.Integer
selected java.lang.Boolean
verticalTextPosition java.lang.Integer
maximumSizeSet java.lang.Boolean
maximumSize java.awt.Dimension
font com.rational.test.ft.value.FontInfo
alignmentY java.lang.Float
requestFocusEnabled java.lang.Boolean
alignmentX java.lang.Float
locationOnScreen java.awt.Point
toolTipText java.lang.String
paintingTile java.lang.Boolean
doubleBuffered java.lang.Boolean
opaque java.lang.Boolean
GuiSubitemTestObject
displayable java.lang.Boolean
height java.lang.Integer
selectedIndex java.lang.Integer
backgroundAt [Ljava.lang.Object;
visible java.lang.Boolean
lightweight java.lang.Boolean
y java.lang.Integer
x java.lang.Integer
visibleRect java.awt.Rectangle
boundsAt [Ljava.lang.Object;
verifyInputWhenFocusTarget java.lang.Boolean
validateRoot java.lang.Boolean
minimumSize java.awt.Dimension
focusTraversable java.lang.Boolean
focus java.lang.Boolean
focusOwner java.lang.Boolean
width java.lang.Integer
debugGraphicsOptions java.lang.Integer
backgroundSet java.lang.Boolean
focusable java.lang.Boolean
fontSet java.lang.Boolean
foregroundSet java.lang.Boolean
font com.rational.test.ft.value.FontInfo
minimumSizeSet java.lang.Boolean
tabPlacement java.lang.Integer
focusTraversalPolicySet java.lang.Boolean
enabled java.lang.Boolean
toolTipTextAt java.lang.String
preferredSize java.awt.Dimension
class java.lang.String
locationOnScreen java.awt.Point
focusCycleRoot java.lang.Boolean
bounds java.awt.Rectangle
doubleBuffered java.lang.Boolean
foreground java.awt.Color
tabLayoutPolicy java.lang.Integer
managingFocus java.lang.Boolean
displayedMnemonicIndexAt [Ljava.lang.Object;
foregroundAt [Ljava.lang.Object;
maximumSizeSet java.lang.Boolean
valid java.lang.Boolean
background java.awt.Color
componentCount java.lang.Integer
tabRunCount java.lang.Integer
requestFocusEnabled java.lang.Boolean
toolTipText java.lang.String
mnemonicAt [Ljava.lang.Object;
ignoreRepaint java.lang.Boolean
uIClassID java.lang.String
showing java.lang.Boolean
name java.lang.String
selectedTabBold java.lang.Boolean
paintingTile java.lang.Boolean
location java.awt.Point
focusTraversalKeysEnabled java.lang.Boolean
cursorSet java.lang.Boolean
tabCount java.lang.Integer
alignmentY java.lang.Float
preferredSizeSet java.lang.Boolean
alignmentX java.lang.Float
opaque java.lang.Boolean
titleAt [Ljava.lang.Object;
maximumSize java.awt.Dimension
optimizedDrawingEnabled java.lang.Boolean
autoscrolls java.lang.Boolean
size java.awt.Dimension
TextSelectGuiSubitemTestObject
selectedIndex java.lang.Integer
y java.lang.Integer
x java.lang.Integer
cursorSet java.lang.Boolean
backgroundSet java.lang.Boolean
optimizedDrawingEnabled java.lang.Boolean
minimumSizeSet java.lang.Boolean
focusCycleRoot java.lang.Boolean
popupWidth java.awt.Dimension
visibleRect java.awt.Rectangle
toolTipText java.lang.String
maximumSize java.awt.Dimension
debugGraphicsOptions java.lang.Integer
preferredSizeSet java.lang.Boolean
width java.lang.Integer
editable java.lang.Boolean
managingFocus java.lang.Boolean
enabled java.lang.Boolean
valid java.lang.Boolean
alignmentY java.lang.Float
preferredSize java.awt.Dimension
alignmentX java.lang.Float
actionCommand java.lang.String
name java.lang.String
maximumRowCount java.lang.Integer
bounds java.awt.Rectangle
autoscrolls java.lang.Boolean
focusTraversalKeysEnabled java.lang.Boolean
foregroundSet java.lang.Boolean
focus java.lang.Boolean
uIClassID java.lang.String
focusTraversable java.lang.Boolean
maximumSizeSet java.lang.Boolean
paintingTile java.lang.Boolean
fontSet java.lang.Boolean
verifyInputWhenFocusTarget java.lang.Boolean
displayable java.lang.Boolean
doubleBuffered java.lang.Boolean
height java.lang.Integer
itemCount java.lang.Integer
requestFocusEnabled java.lang.Boolean
focusOwner java.lang.Boolean
validateRoot java.lang.Boolean
showing java.lang.Boolean
lightweight java.lang.Boolean
visible java.lang.Boolean
class java.lang.String
foreground java.awt.Color
popupVisible java.lang.Boolean
locationOnScreen java.awt.Point
mandatory java.lang.Boolean
background java.awt.Color
focusTraversalPolicySet java.lang.Boolean
minimumSize java.awt.Dimension
opaque java.lang.Boolean
location java.awt.Point
componentCount java.lang.Integer
focusable java.lang.Boolean
font com.rational.test.ft.value.FontInfo
lightWeightPopupEnabled java.lang.Boolean
ignoreRepaint java.lang.Boolean
size java.awt.Dimension
TextGuiSubitemTestObject
foreground java.awt.Color
background java.awt.Color
text java.lang.String
format java.lang.Boolean
maximumSize java.awt.Dimension
optimizedDrawingEnabled java.lang.Boolean
minimumSizeSet java.lang.Boolean
valid java.lang.Boolean
nonEditableForegroundColor java.lang.String
autoscrolls java.lang.Boolean
componentCount java.lang.Integer
showing java.lang.Boolean
bounds java.awt.Rectangle
managingFocus java.lang.Boolean
lightweight java.lang.Boolean
focusOwner java.lang.Boolean
alignmentY java.lang.Float
alignmentX java.lang.Float
class java.lang.String
verifyInputWhenFocusTarget java.lang.Boolean
width java.lang.Integer
scrollOffset java.lang.Integer
preferredSize java.awt.Dimension
minimumSize java.awt.Dimension
scrollableTracksViewportWidth java.lang.Boolean
y java.lang.Integer
x java.lang.Integer
selectedText java.lang.String
scrollableTracksViewportHeight java.lang.Boolean
opaque java.lang.Boolean
displayable java.lang.Boolean
focusable java.lang.Boolean
nonEditableBackgroundColor java.lang.String
focus java.lang.Boolean
name java.lang.String
fontSet java.lang.Boolean
focusTraversable java.lang.Boolean
columns java.lang.Integer
editableForegroundColor java.lang.String
visible java.lang.Boolean
locationOnScreen java.awt.Point
toolTipText java.lang.String
selectedTextColor java.awt.Color
preferredSizeSet java.lang.Boolean
selectionTextColor java.lang.String
focusTraversalKeysEnabled java.lang.Boolean
editable java.lang.Boolean
debugGraphicsOptions java.lang.Integer
location java.awt.Point
selectionColor java.awt.Color
preferredScrollableViewportSize java.awt.Dimension
spaceEnabled java.lang.Boolean
disabledTextColor java.awt.Color
ignoreRepaint java.lang.Boolean
selectionEnd java.lang.Integer
focusCycleRoot java.lang.Boolean
textSelectionColor java.lang.String
doubleBuffered java.lang.Boolean
cursorSet java.lang.Boolean
font com.rational.test.ft.value.FontInfo
requestFocusEnabled java.lang.Boolean
type java.lang.Integer
caretPosition java.lang.Integer
foregroundSet java.lang.Boolean
editableBackgroundColor java.lang.String
height java.lang.Integer
mandatory java.lang.Boolean
horizontalAlignment java.lang.Integer
dragEnabled java.lang.Boolean
enabled java.lang.Boolean
focusTraversalPolicySet java.lang.Boolean
focusAccelerator java.lang.Character
maximumSizeSet java.lang.Boolean
visibleRect java.awt.Rectangle
backgroundSet java.lang.Boolean
validateRoot java.lang.Boolean
paintingTile java.lang.Boolean
size java.awt.Dimension
selectionStart java.lang.Integer
uIClassID java.lang.String
caretColor java.awt.Color
InternalFrameTestObject
maximum java.lang.Boolean
fontSet java.lang.Boolean
cursorSet java.lang.Boolean
bounds java.awt.Rectangle
lightweight java.lang.Boolean
normalBounds java.awt.Rectangle
doubleBuffered java.lang.Boolean
y java.lang.Integer
uIClassID java.lang.String
x java.lang.Integer
verifyInputWhenFocusTarget java.lang.Boolean
maximumSizeSet java.lang.Boolean
moduleName java.lang.String
closable java.lang.Boolean
opaque java.lang.Boolean
selected java.lang.Boolean
location java.awt.Point
focusOwner java.lang.Boolean
focus java.lang.Boolean
screenLoadAction java.lang.String
foregroundSet java.lang.Boolean
maximizable java.lang.Boolean
focusTraversalPolicySet java.lang.Boolean
resizable java.lang.Boolean
closedFromProcessPrevious java.lang.Boolean
markedFlightNumbers java.lang.String
validateRoot java.lang.Boolean
autoscrolls java.lang.Boolean
backgroundSet java.lang.Boolean
optimizedDrawingEnabled java.lang.Boolean
requestFocusEnabled java.lang.Boolean
managingFocus java.lang.Boolean
foreground java.awt.Color
focusTraversable java.lang.Boolean
toolTipText java.lang.String
closed java.lang.Boolean
focusCycleRoot java.lang.Boolean
visibleRect java.awt.Rectangle
enabled java.lang.Boolean
icon java.lang.Boolean
font com.rational.test.ft.value.FontInfo
showing java.lang.Boolean
minimumSize java.awt.Dimension
layer java.lang.Integer
defaultCloseOperation java.lang.Integer
iconifiable java.lang.Boolean
class java.lang.String
minimumSizeSet java.lang.Boolean
preferredSize java.awt.Dimension
maximumSize java.awt.Dimension
height java.lang.Integer
warningString java.lang.String
instanceID java.lang.String
subModuleName java.lang.String
background java.awt.Color
focusTraversalKeysEnabled java.lang.Boolean
locationOnScreen java.awt.Point
width java.lang.Integer
alignmentY java.lang.Float
alignmentX java.lang.Float
title java.lang.String
componentCount java.lang.Integer
debugGraphicsOptions java.lang.Integer
displayable java.lang.Boolean
mainScreen java.lang.Boolean
focusable java.lang.Boolean
paintingTile java.lang.Boolean
ignoreRepaint java.lang.Boolean
valid java.lang.Boolean
visible java.lang.Boolean
preferredSizeSet java.lang.Boolean
size java.awt.Dimension
ToggleGUITestObject
focus class java.lang.Boolean
paintingTile class java.lang.Boolean
showing class java.lang.Boolean
requestFocusEnabled class java.lang.Boolean
location class java.awt.Point
horizontalAlignment class java.lang.Integer
managingFocus class java.lang.Boolean
y class java.lang.Integer
borderPainted class java.lang.Boolean
x class java.lang.Integer
displayable class java.lang.Boolean
font class com.rational.test.ft.value.FontInfo
multiClickThreshhold class java.lang.Long
displayedMnemonicIndex class java.lang.Integer
mnemonic class java.lang.Integer
componentCount class java.lang.Integer
validateRoot class java.lang.Boolean
preferredSizeSet class java.lang.Boolean
focusPainted class java.lang.Boolean
debugGraphicsOptions class java.lang.Integer
optimizedDrawingEnabled class java.lang.Boolean
class class java.lang.String
opaque class java.lang.Boolean
alignmentY class java.lang.Float
fontSet class java.lang.Boolean
alignmentX class java.lang.Float
rolloverEnabled class java.lang.Boolean
uIClassID class java.lang.String
ignoreRepaint class java.lang.Boolean
focusTraversable class java.lang.Boolean
minimumSize class java.awt.Dimension
locationOnScreen class java.awt.Point
iconTextGap class java.lang.Integer
valid class java.lang.Boolean
toolTipText class java.lang.String
autoscrolls class java.lang.Boolean
focusTraversalKeysEnabled class java.lang.Boolean
verifyInputWhenFocusTarget class java.lang.Boolean
text class java.lang.String
focusCycleRoot class java.lang.Boolean
lightweight class java.lang.Boolean
maximumSizeSet class java.lang.Boolean
contentAreaFilled class java.lang.Boolean
verticalTextPosition class java.lang.Integer
enabled class java.lang.Boolean
backgroundSet class java.lang.Boolean
selected class java.lang.Boolean
foregroundSet class java.lang.Boolean
cursorSet class java.lang.Boolean
maximumSize class java.awt.Dimension
name class java.lang.String
focusOwner class java.lang.Boolean
visible class java.lang.Boolean
width class java.lang.Integer
foreground class java.awt.Color
focusable class java.lang.Boolean
doubleBuffered class java.lang.Boolean
verticalAlignment class java.lang.Integer
visibleRect class java.awt.Rectangle
minimumSizeSet class java.lang.Boolean
bounds class java.awt.Rectangle
background class java.awt.Color
label class java.lang.String
horizontalTextPosition class java.lang.Integer
size class java.awt.Dimension
height class java.lang.Integer
actionCommand class java.lang.String
preferredSize class java.awt.Dimension
focusTraversalPolicySet class java.lang.Boolean
SelectGuiSubitemTestObject
location java.awt.Point
.itemCount java.lang.Integer
visible java.lang.Boolean
maximumSize java.awt.Dimension
scrollableTracksViewportHeight java.lang.Boolean
focusCycleRoot java.lang.Boolean
validateRoot java.lang.Boolean
firstVisibleIndex java.lang.Integer
cursorSet java.lang.Boolean
selectedIndex java.lang.Integer
foregroundSet java.lang.Boolean
valueIsAdjusting java.lang.Boolean
backgroundSet java.lang.Boolean
y java.lang.Integer
x java.lang.Integer
enabled java.lang.Boolean
lastVisibleIndex java.lang.Integer
ignoreRepaint java.lang.Boolean
opaque java.lang.Boolean
valid java.lang.Boolean
verifyInputWhenFocusTarget java.lang.Boolean
bounds java.awt.Rectangle
selectionBackground java.awt.Color
selectionMode java.lang.Integer
autoscrolls java.lang.Boolean
focusable java.lang.Boolean
optimizedDrawingEnabled java.lang.Boolean
displayable java.lang.Boolean
layoutOrientation java.lang.Integer
toolTipText java.lang.String
focusTraversalPolicySet java.lang.Boolean
selectionEmpty java.lang.Boolean
focus java.lang.Boolean
maxSelectionIndex java.lang.Integer
dragEnabled java.lang.Boolean
locationOnScreen java.awt.Point
requestFocusEnabled java.lang.Boolean
minimumSizeSet java.lang.Boolean
foreground java.awt.Color
scrollableTracksViewportWidth java.lang.Boolean
fixedCellWidth java.lang.Integer
font com.rational.test.ft.value.FontInfo
focusTraversalKeysEnabled java.lang.Boolean
preferredScrollableViewportSize java.awt.Dimension
size java.awt.Dimension
width java.lang.Integer
anchorSelectionIndex java.lang.Integer
class java.lang.String
lightweight java.lang.Boolean
focusOwner java.lang.Boolean
uIClassID java.lang.String
name java.lang.String
showing java.lang.Boolean
componentCount java.lang.Integer
.itemText com.rational.test.ft.value.NameSet
minimumSize java.awt.Dimension
doubleBuffered java.lang.Boolean
debugGraphicsOptions java.lang.Integer
height java.lang.Integer
fontSet java.lang.Boolean
leadSelectionIndex java.lang.Integer
paintingTile java.lang.Boolean
focusTraversable java.lang.Boolean
alignmentY java.lang.Float
alignmentX java.lang.Float
fixedCellHeight java.lang.Integer
minSelectionIndex java.lang.Integer
managingFocus java.lang.Boolean
preferredSize java.awt.Dimension
background java.awt.Color
preferredSizeSet java.lang.Boolean
visibleRowCount java.lang.Integer
maximumSizeSet java.lang.Boolean
selectionForeground java.awt.Color
visibleRect java.awt.Rectangle

Listing Object Properties

I frequently need to deal with object properties, i.e. those that are returned from the myObject().getProperties(); calls. E.g. to get the value displayed in a Label, you’d write something like: myLabel().getProperty("text");. Getting the list of properties is a painfully annoying process, so here’s some code to do it for you.

The method takes in any of Rational’s GUI object types (i.e. GuiTestObject and anything that inherits from that), and then dumps a list of the properties, with the class of object that is returned. You can put this method in any Rational script (doesn’t work in an ordinary java class), and run it from there. A sensible place would be the script where all your objects are contained – if you’ve gone with the single object map idea.


/*
* 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.
*
*/

public void printInfo(GuiTestObject gto)
{
Hashtable ht = gto.getProperties();
Enumeration e = ht.keys();
System.out.println(“====================”);
System.out.println(gto.getClass().toString());
System.out.println(“——————–”);

do
{
try
{
Object sKey = e.nextElement();
Object sValue = ht.get(sKey);
System.out.println(sKey.toString() + “,” + sValue.getClass().toString() + “,” + sValue.toString());
}
catch(Exception ex)
{
System.err.println(ex.getMessage());
}
} while(e.hasMoreElements());
}

Managing the Applications Under Test config file

When you configure an application to be tested in Rational Functional Tester, it doesn’t save it at the project level, but only on the local machine. This is a pain. Everyone on the team needs to follow a setup routine everytime a new version of the app comes out (this may not always be true, but it usually is), and someone always gets it wrong. Very annoying. What would make the whole process easier is if that configuration would be at the project level, but it’s not. Enough complaining.

A fix is for one person to maintain the application configuration, and send everyone on the team a copy once it’s been updated. The config file lives here:

C:\Documents and Settings\All Users\Application Data\IBM\RFT\configuration\configurations.rftcfg

If you can’t find it there, the directory is set in the registry under the following details:
Path: “My Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Rational Software\Rational Test\8″
String: “Rational FT Configuration Directory”

The value in that string is the directory that the “configurations.rftcfg” file should be in.