Proxy development best practices
Following best practices while you develop proxies can help make your work more efficient and effective. Consider these methods to enhance your development efforts.
Use the appropriate hierarchy for GUI objects
GUI objects are arranged in two related hierarchies: parent-child and owner-owned. An example of parent-child relationship is a dialog box and a contained button. An example of an owner-owned relationship is a top-level window and a dialog box. Use any one type of hierarchy for an object.
In proxy implementation, it is common for the underlying object model (for example, Java and HWND) to confuse these two relationships, and treats the owner-owned relationship as an asymmetric parent-child relationship. In this case, the proxy must deny having a parent when the preferable relationship model is owner/owned. The methods that can be used for going through the hierarchy are getParent(), getChildren(), getOwner(), and getOwned().
Avoid returning different types for the same property
Properties are named values. The property itself does not have a type; the value has a type. Avoid making proxies return different types for the same property. Sometimes a property value can be a reference to an object rather than a value. If such a value is returned to a script, it is returned as a TestObject. The methods to access the properties include getProperty(), setProperty(), getProperties(), and getNonValueProperties().
Use the Object Library to assign recognition properties and weights for the objects
By default, the new proxy objects might not have object recognition properties and weights. Use the Object Library to assign the recognition properties and weights. The methods for accessing the object recognition properties and weights are getRecognitionProperties() and getRecognitionPropertyWeight(). If more than one object of the same class exists within the parent object, add the .classIndex property (a positive numeric value starting at 0), as a recognition property for the child object.
Manage mappable hierarchies
Generally, the entire hierarchy of the objects are mapped. However, certain objects are likely to change frequently between builds of the test application. For example, in Java, it is common to add panels to cluster objects together. With Functional Tester the user can specify not to map the proxy object. Even though the non-mappable objects are not in the test object map, the object hierarchy lists them while you traverse through the parent-child hierarchy. The methods for managing the mappable hierarchy include shouldBeMapped(), getMappableParent(), and getMappableChildren().
Use canonical properties
In some cases, the underlying object model supports a notion of properties, for example, Java, HTML, and .NET. Functional Tester allow proxies to implement additional properties. If a proxy implements a property directly, the property name must have a different pattern to avoid confusion with any property of the object. Begin the regular properties name that might be used for recognition should with a dot (.). Certain administrative properties are used by the framework that cannot be used for recognition, these property names begin with a number sign (#).
Invoking object methods
In many cases, the underlying object has methods that can be found and invoked. These are usually managed directly by the framework and the domain implementation, but getMethod() is commonly implemented on a base proxy in a domain.
Use well-defined scriptable methods
Make mouse actions play back from the glass whenever possible. If a method name includes "click" or "drag", have mouse events perform the action . Do not use method names like "click" or "drag" if mouse events are not used to implement the action. Do not use method names that refer to keys or the keyboard if keyboard events do not implement the action. Make the methods reflect the action that is going to be performed and reliable during playback. Avoid heuristics.
Objects can contain other objects and might have an internal structure that is not exposed as a nested object or objects. For example, a list might have items in it, but the items are not exposed by the list object as objects themselves. This kind of behavior is common in HWND-based objects. The most common method to deal with subitems are getSubitem() and the mouse action methods such as click(), drag(), and doubleClick(). The getSubitem() method returns a null or a string.
Use any of the following strategies if you do not want the objects in the subitems to be exposed as full-fledged objects:
- Declare the subitem as not mappable
Declare the subitem proxy as not mappable. The object at point talks to its parent and the parent proxy is responsible for recording actions against the aggregate object and for supporting playback of subitem-based GUI actions.
- Make the subitem delegate the call to its parent
During recording the subitem proxy passes the processMouseEvent() calls to its parent. The parent proxy is responsible for recording actions against the aggregate object and for supporting playback of subitem-based GUI actions.
- Make the subitem delegate recording actions to its parent
During recording the subitem proxy processes processMouseEvent() calls and generates the method calls on the parent object. The parent proxy is not responsible for recording actions against the aggregate object but is responsible for supporting playback of subitem-based GUI actions.
- Use child objects of subitems
Have a new kind of object reference that is tagged so that the reference is unregistered after it is used as an anchor. This enables anchoring an object using subitems of another object. You can map the nested object as a child of the parent object.
Exceptions and Errors
Follow these rules while implementing exceptions and errors:
- Use public, documented exceptions
Do not throw private or internal exceptions from the proxies. The API documentation for your proxies might not be available. Use standard exceptions, preferably RationalTestExceptions.
- Re-use exceptions
Re-use the exceptions from the com.rational.test.ft package in Java or the Rational.Test.Ft namespace in .Net. If a java proxy throws a com.rational.test.ftMethodNotFoundException exception and the script is written in VB, the VB script gets a Rational.Test.Ft.MethodNotFoundException exception. If you throw an exception that does not have a name that begins with com under com.rational.test.ft it gets marshalled as a WrappedException exception.
- Use constructors
All RationalTestExceptions that can be marshalled must support a constructor that takes a single string parameter.
- Make parallel implementations of .Net and Java exceptions
If you add a new exception in a proxy implemented in Java that you expect to be able to be returned to the client, ensure you implement the same exception in .Net.
- Declare runtime exceptions
In Java, exceptions must be declared , which might not be helpful for some testers. Many exceptions arise from almost any GUI method, so use runtime exceptions instead of exceptions in Java. Avoid using errors. An Error should cause the entire playback or recorder session to stop.
- Include ObjectNotFound exceptions
If the object is not found, the framework throws an ObjectNotFoundException exception. If the object is found, and a subitem is specified but not found, the proxy must throw a SubItemNotFoundException exception. The SubItemNotFoundException is detected by the framework, and it retries automatically.
- Manage coordinate-based clicks
If the input coordinates click an object or subitem that is beyond the region, change the coordinates to include the region in the object or subitem. Add a mechanism to generate a warning in the log when this occurs. The proxy might have to use coordinate-based clicks because the object screen layout cannot be completely described. For example, on a JTree, the PLUS_MINUS geometry is not known, but it can be found relative to the subitem to which it applies. It is acceptable for the proxy to expand the area of the subitem to include the PLUS_MINUS. You can use negative coordinates for subitems. Document all violations of the normal behavior. Ensure that no subitems with a specified coordinate-click click beyond the object.
- Manage exceptions when wrong objects are clicked
If a wrong object is clicked, throw a com.rational.test.ft.CoordinateOnWrongObjectException exception. The wrong object might overlap the correct target. You can change the coordinates to avoid the child object within a container. Ignore the specified point and look for another point an appropriate object to click. Avoid recording coordinates on objects that have mappable children and do not allow clicks on the wrong objects.
- Manage exceptions when wrong subitems are clicked
If a wrong subitem is clicked, throw a com.rational.test.ft.CoordinateOnWrongSubitemException exception. This exception does not apply to clicks associated with an object where a subitem is not specified. This type of click applies only when the object and any subitem in that object is clicked. In this case, the wrong subitem overlaps the correct target, and is probably a child. Avoid recording the coordinates on subitems that have nested subitems to avoid this exception. Ignore the specified point and look for another point on an appropriate subitem to click.