The testobject. Find method is a powerful part of functional tester, making it easier to maintain automated scripts. This introductory article shows you how to introduce testobject. Find to your automation framework.
Part 1: Basics of the testobject. Find Method
The testobject. Find method is a Java? Method, IBM? Rational? The functional tester (rft) tool uses it to dynamically locate testobject in the tested application (application under test, AUT) at runtime. By using it, you can avoid having to record the action to add the testobject object to the object map (Object map.
The mapped object is verified using the stored, static, recognition attribute, and object hierarchy. The script uses the correct control during playback. Although it is fast to use recorded objects for object recognition, it is time-consuming to update attributes, especially when you need to set the object's attribute weights, or when the text attribute is changed to the regular expression (RegEx) value. The find method provides you with an option to exclude most of the recorded controls from object maps.
The testobject. Find method is more robust in rft 6.x. Currently, the performance is almost the same as that of the ing object.
Benefits of using the find Method
One of the best reasons to replace object map with find is that you can easily change the control recognition attributes stored in Java or property files. The advantage is that you do not need to change the recognition attributes stored in the object map (Object map), so that you do not need to use the object map (Object map )) A more lengthy and time-consuming Method for UI changes or record objects to update.
Understanding and using find
To understand the find method and its relationship to the ing object, consider controls in applications that may change. Therefore, you need to update the object map (Object map )). Some simple control methods, for example, an application may change the tag of its USER command button during version update. For example, your aut may contain a dialog box that contains a button labeled as open. In previous versions, the button label is OK. For the next version, the button tag is changed back to open, but there will be an open... .
If you record the OK button to the object map (Object map), you will need to change the recognition attribute to adapt to tag changes, and you will need to record the new open... Button. (For this instance, possible changes to the object hierarchy in the application due to UI changes will be ignored .)
Next, assume that the dialog box contains other buttons, such as cancel and help. You can see that the buttons can be differentiated by labels, even if they appear in different order in the application in the future. Therefore, as long as you can distinguish these buttons by text on tags, you do not need to consider the index attribute or any other attributes.
Use classicsjavaa to explore the find Method
You can also use rft to obtain information about the controls you may need later. For this example, use the classicsjavaa sample application provided by rft and follow the steps below.
- When you define the properties of a button, create a temporary empty functional test script to retain the object map ).
- In the menu of the empty test script, select SCRIPT> open test object map.
- Select Applications> classicsjavaa to start the application.
- Click place order.
- Click the OK button in the member logon dialog box.
Now the place an order dialog box appears. You can use this dialog box to observe how to use the find method to locate the button in the dialog box and obtain a testobject for each control.
Figure 1. place an order dialog box in the classicsjavaa Application
You will see three buttons in the next dialog box: related items, place order, and cancel. Observe the three buttons in the object map, and then proceed with the following steps:
- In the private test object map, select Test Object> insert object (s) from the menu ).
- Drag the object finder control to the place an order dialog box and move it to the title bar so that the entire dialog box is surrounded by a red box, and then release the mouse button.
- Now, in the insert a GUI object into the object map dialog box, select include all available objects on this window and click Finish.
- Click place order.
- Your current object map should contain a javax. Swing. jframe object. Select the jframe control so that you can see the recognition attribute of the dialog box. For this control, labels or text are the two most important attributes that define the control. The second important property is the control class, because it may display many
Jframe object, but only one label may be place an order. Follow these steps:
- Display Card hierarchy, find the button label.
- Select the cancel button to analyze the recognition attribute that rft uses to describe the button in object map. Four attributes are listed here, and two of them are crucial for defining the correct buttons: class and accessiblecontext. accessiblename attributes (see figure 2 ).
Figure 2. instance of object map using classicsjavaa Application
- Find the correct button. Many dialogs contain a Cancel button. Therefore, you must first find the testobject dialog box that contains the correct cancel button. If you first find the correct dialog box, it is easier to find the correct button in the dialog box.
- Return to your empty test script. Because the dialog box is an advanced object, you can define roottestobject to start searching for testobject. After you finish this,
- You can use the find method to locate the testobject dialog box:
Roottestobject root = getroottestobject ();
- You are ready to use the find method to locate the place an order dialog box and use the class information of the window.
Note: Make sure that all testobject attributes you have found are printed so that you can check them.
Your command should be similar to the following:
// Get all test objects of Type jframe (DIALOG) Testobject [] to = root. Find (atdescendant ("class", "javax. Swing. jframe ")); // Print dialog test object properties to console For (INT I = 0; I <to. length; I ++) { System. Out. println (to [I]. getproperties ()); } |
The result should be similar to the following (except for most attributes, to save space ):
{Height = 600, displayable = true, undecorated = false ,..., Class = javax. Swing. jframe, Title = place an order ,...} |
Next, use the find method to replace the above Code, and use the label Text of the window in the dialog box to locate the place an order dialog box:
// Get all test objects that have the title "place an order" Testobject [] to = root. Find (atdescendant ("title", "place an order "));// Print test object properties to console For (INT I = 0; I <to. length; I ++) { System. Out. println (to [I]. getproperties ()); } |
In either case, you will find that only one object is the same as the displayed Property. This is the ideal situation. To increase the possibility of the result in each case, you can combine the two attributes into a find call:
// Get all test objects of Type jframe (DIALOG) // And have the caption "place an order" Testobject [] to = root. Find (atdescendant ("class", "javax. Swing. jframe ", "Title", "place an order ")); |
Now that you have found the control that contains the tag you searched for, you can use find to locate the correct button:
// Capture the correct dialog as a test object Testobject toplaceanorderdialog = to [0];// Reuse the test object array, finding all buttons on // "Place an order" dialog that have the caption "cancel" To = toplaceanorderdialog. Find (atdescendant ("class", "javax. Swing. jbutton ", "Text", "cancel ")); // Verify that only one button was found System. Out. println (to. Length ); // Capture the correct button as a guitestobject Guitestobject cancelbutton = new guitestobject (to [0]); |
You can call the find method from any testobject. This depends on the object you selected, and the search is only limited to the objects at the lower level under the object you selected.
In the above example, the Code uses the atdescendant button to locate. However, you can use find in many ways:
- Atchild searches for all direct sub-objects of testobject.
- Atdescendant searches for all the sub-objects of testobject.
- Atlist allows you to specify a list of atchild, atdescendant, and atproperty objects, so that you can reduce the search range.
Part 1: Examples of actual applications using testobject. Find
Testing various attributes will help you determine which attribute works best when looking for objects in an application. Once you understand how the find method can help you dynamically define controls, you can start to write the getter method, so that you can not rely on the recorded object map (Object map) to locate the object.
Define controls as part of the dialog box
For example, for the place an order dialog box, you may decide to define the control as part of the dialog box. In this case, you should first find the dialog box, and then find the control you want to modify in the dialog box. For this situation, your code design should be as follows:
Public class placeanorder { Public static guitestobject getdialog () { Roottestobject root = getroottestobject (); Testobject [] to = root. Find (atdescendant ("title", "place an order ")); Return new guitestobject (to [0]); } Public static guitestobject getbuttoncancel () { Testobject [] to = getdialog () . Find (atdescendant ("class", "javax. Swing. jbutton ", "Text", "cancel ")); Return new guitestobject (to [0]); } } |
Here is an example of how to use these methods in the script:
Public void testmain (object [] ARGs) { // Find the place an order Dialog Guitestobject dialogplaceanorder = placeanorder. getdialog (); Guitestobject cancelorder = placeanorder. getbuttoncancel (); Cancelorder. Click (); } |
To find a common object definition method
To find more common button labels, such as cancel, you may need to develop more common methods to find any button in your application. For example, you can use getbutton ("cancel", placeanorderdialog), where the source is the parent window. For the second scenario, your design should be similar to this instance:
Public class classicsjavaui { Public static guitestobject getbutton (string buttonname, Testobject parent) { Testobject [] to = parent. Find (subitemfactory. atdescendant ("Class", "javax. Swing. jbutton", "text", buttonname )); Return (New guitestobject (to [0]); } Public static guitestobject getbutton (string buttonname) { Roottestobject root = rationaltestscript. getroottestobject (); Testobject [] to = root. Find (subitemfactory. atdescendant ("Class", "avax. Swing. jbutton", "text", buttonname )); Return (New guitestobject (to [0]); } Public static guitestobject getdialog (string dialogname) { Roottestobject root = rationaltestscript. getroottestobject (); Testobject [] to = root. Find (subitemfactory. atdescendant ("Class", "javax. Swing. jframe", "title", dialogname )); System. Out. println (to. Length ); Return (New guitestobject (to [0]); } } Public class placeorderwindow { Public static guitestobject getdialog () { Return classicsjavaui. getdialog ("place an order "); } Public static guitestobject getbuttonplaceorder () { Return classicsjavaui. getbutton ("place an order", getdialog ()); } } |
Here is an example of how you can use these methods in the script, or, more appropriately, use the class that defines the place an order dialog box:
Public void testmain (object [] ARGs) { Guitestobject dialog = placeorderwindow. getdialog (); Guitestobject buttonplaceorder = Placeorderwindow. getbuttonplaceorder (); Buttonplaceorder. Click (); } |
The application you are testing will determine how you define the methods for finding controls. The following is an example of how the system is designed around the find method.
Use the rft find method in eclipse-based applications
The example of using the find method in eclipse-based applications is only limited to one part of the AUT, as a way to get the design of the object getter method. Objects in this application have identifiable patterns. Standard SWT objects are mainly used, but there are some specialized custom classes provided by the application development team.
Test developers create a common method to obtain all objects of a specific class, or obtain an object with a given index number under a specific parent object. To make the application work automatically on a local version of the application, the test developer decides to use the object index as the key attribute for finding the object, rather than text. The classes described below will be used to do this.
Note: All methods in these classes are static, so the test developer can use these methods without instantiating the class as an object. You can call them in the following format: <Class Name>. <Method Name> (<parameters> ).
The findappobjects. Java class allows you to use two different methods: getallobjects and getobjectatindex. These methods are generally not directly used, but they are the basis of other methods. However, you can use them to determine which index numbers are used to find objects.
/** * Given a parent object, find all Descendant Test objects with * Given class. * @ Param parent testobject * @ Param classname string * @ Return array of testobject or null if no objects of Type * Classname were found. */ Public static testobject [] getallobjects (testobject parent, String classname) |
Getallobjects uses the parent object of the testobject type and the string type as the input, and returns an array of testobject containing all the sub-objects of the specific type of the parent object. This instance returns all the sub-dialogs of roottestobject:
Roottestobject root = getroottestobject (); Testobject [] dialogs = Findappobjects. getallobjects (root, "javax. Swing. jframe "); |
It is important to select the correct parent testobject object so that you can obtain only the objects you are looking for from the results. As an instance, assume that the following part represents an object hierarchy in the AUT:
Application Composite Group0 Button0 Button1 Group1 Button0 Button1 |
Calling getallobjects (application, "button") returns an array containing four buttons. However, if you do not scan the array cyclically and print each index number and button [Index]. if the getproperty ("text") string is used, you cannot quickly determine which index numbers match which buttons.
To replace this troublesome process, it makes more sense to call more than one layer:
// Get all groups in the Application Testobject [] groups = findappobjects. getallobjects (Application, "group "); // Limit search to only buttons in the first group found Testobject [] buttons = findappobjects. getallobjects (Groups [0], "button "); // Click the first button found under the Group New button (to [0]). Click (); |
The getallobjects (group0, "button") call returns only two buttons, which are probably in the correct order (button0, then button1), as shown on the screen. If there are only some buttons in the entire application or dialog box, it is easier to obtain all the buttons and calculate the index.
/** * Given a parent object, find the descendent test object * With a given class, at a given one-based index. * * @ Param parent testobject * @ Param classname string * @ Param index int, zero-based index * @ Return testobject or null if index is greater * The total number of objects found. */ Public static testobject getobjectatindex (Testobject parent, string classname, int index) |
Getobjectatindex refines the use of getallobjects. It obtains a parent testobject object, a string object of the string class, and a zero-based integer, and then returns a single testobject object. For example, this code returns the first button under the specified (parent) group:
Testobject to = getobjectatindex (group1, button, 0 ); |
All of these methods return a testobject object, and those objects may not be of the specific type you need to find. Both of the above methods return a general testobject object. Often, you want to use objects of specific types. When using these methods, make sure that the returned testobject object is explicitly converted to the correct type before you use the object in code.
The findbasicappobjects. Java class provides further refinement and assistance. It is a subclass of findappobjects. Java and uses the getobjectatindex method. It contains the getter method of the sub-object that returns the index number of the testobject parent object. At this time, the product object has been converted into a correct class, so you do not need to convert it again. This instance returns a subset of the standard Eclipse SWT widget class, such as org. Eclipse. SWT. Widgets. Button:
/** * Find the index-specified org. Eclipse. SWT. Widgets. Button * Child control under the specified parent. * * @ Param parent testobject * @ Param index int, zero-based * @ Return wbutton */ Public static wbutton getbutton (testobject parent, int index) |
Getdialog is the only method in findbasicappobjects. Java that does not require a parent object, because it assumes that the parent object is aut. To identify the correct dialog box, even if the title of the dialog box is changeable, getdialog uses the regular expression (RegEx) object as a parameter, as shown below:
/** * Find A org. Eclipse. SWT. Widgets. Shell Control * With a caption specified by the given * Regular Expression (RegEx ). * * @ Param dialogcaption RegEx object containing dialog's * Expected Caption * @ Return wframe */ Public static wframe getdialog (RegEx dialogcaption) |
Compare the code of the place an order dialog box (beginning with this section) with the same behavior of using findappobjects and findbasicappobjects in the following instance. Assume that the place an order dialog box is an eclipse dialog box of the wframe type, and the button is of the wbutton type.
Public class placeanorder extends rationaltestscript { Private Final int cancel = 2; Private Final RegEx dialog_caption = new RegEx ("^ Place an order $ "); Public wframe getdialog () { Return findbasicappobjects. getdialog (dialog_caption ); } Public wbutton getbuttoncancel () { Return findbasicappobjects. getbutton (getdialog (), cancel ); } Public void testmain (object [] ARGs) { Getbuttoncancel (). Click (); } } |
The previous code is written in a very easy-to-maintain manner. Every part of the code is separated into easy-to-understand parts. For coding personnel who prefer a more compact layout, the code can also be written in this way:
Public class placeanorder extends rationaltestscript { Public void testmain (object [] ARGs) { Findbasicappobjects. Getbutton (findbasicappobjects. Getdialog (dialog_caption), cancel). Click (); } } |
Always write unit tests
In addition to the getter Method Based on find, the findbasicappobjects. Java class mentioned above also contains basic unit test methods for each defined object type. Each unit test method gets an object of a specific class and a string (the string should be the name of the getter method you are testing ). This name is sent to the console to track the result of passing or failed.
The unit test method first verifies that the provided object is not empty and then performs one or more basic operations on the object. For example, the Unit Test Method of the wbutton object prints the text attribute (TAG) of the object ). You can see whether the getter method returns the correct button.
We recommend that you use the unit test method to test each getter method. Unit Tests are often considered redundant, but after any changes are made to the application's user interface (UI), running unit tests will verify that the methods continue to find the correct controls in the aut, it will confirm that any code change in the getter method can work correctly. Run the unit test to ensure that the test case can be found and the correct object is returned.
/** * Unit test for button controls. * * @ Param B * @ Param methodname name of method under test */ Public static void verifybutton (wbutton B, string methodname) |
Example of calling the Unit Test method:
Findbasicappobjects. Verifybutton (getbuttoncancel (), "getbuttoncancel "); |
Limitations and Suggestions
It is always found between controls. Do not rely on the testobject stored in the code. The object you have found may change between the first time you have found it and the next time you want to use it (or delete and regenerate ). Every time you process an object, you must call the find method to ensure that you get the correct object.
If you use the find method, you cannot record the script. Because your testobject is not defined in object map, the recorder cannot pick out the correct object name in the record. You can still record the Basic Structure Code required by your script, but you need to use the getter Method Based on find to replace the recorded getter method of the ing control.
Many objects may display the same results. When you call the find method, more than one OK button may exist. Make sure that the correct button is obtained by using different properties, such as the dialog box in which the OK button belongs .. Print the result of the getproperties method of testobject to the console to see which attribute can help you differentiate the object you are looking for in a similar object.
Address: http://www.uml.org.cn/test/200612124.htm