Interface AutoTestLocator


public interface AutoTestLocator
An AutoTestLocator is a string generated by the AutoTest class to reliably identify an interactive element in a Smart GWT application. Locators allow integration with automated testing tools. For an overview of automated testing in Smart GWT, see the documentation topic here.

AutoTestLocators are designed to work across browsers, Smart GWT versions, and even major changes to your application's UI. They do not rely on the DOM structure, and are intended to be able to identify the target element reliably without requiring pervasive explicitly specified component IDs.

The AutoTest class is responsible for creating locator strings corresponding to DOM elements, Smart GWT components or other objects, and for resolving locators back to those objects at runtime.

A locator for an element may be retrieved via AutoTest.getLocator(), or by using the locator shortcut tool, or the "Show AutoTest Locators" link on the Results tab of the Smart GWT Developer Console.

Stored locators may be resolved to target elements via AutoTest.getElement() (or resolved to target objects via AutoTest.getObject()).

Best Practices for building applications with reliable locators

Developers should be aware of certain considerations that can make generated AutoTestLocators more reliable when designing their application.

The ReliableLocators overview topic covers general recommendations to ensure that AutoTestLocators are robust and reliable within your app.

The PortableAutoTests topic discusses considerations around recording and playing back test scripts over different environments with changes to data or user interface, and the capabilities Smart GWT offers to address these considerations.

Locator Structure

AutoTest locators consist of a series of segments, delineated by "/" characters.

Each segment identifies a step in a hierarchy from a root component to the target element. Individual segments may represent a Canvas, a FormItem, an interior DOM element or some other construction specific to the locator in question.

Note that the segments in an AutoTestLocator do not necessarily match parent-child relationships in the widget hierarchy.

Root locator segment The root component of a locator may designated in one of the following ways:

  • Component ID: If a component has an explicitly specified ID this may be used along with the class of the widget to reliably identify it, regardless of where it is in the page's widget hierarchy.
    For example a VLayout with ID "leftPane" would be identified as:

    //VLayout[ID="leftPane"]

    Or, if Canvas.locateByIDOnly is true, the class of the widget will not be recorded - the locator segment to identify the root will be just the widget ID prefixed by three slash characters - for example:

    ///leftPane

  • Locator Test Root: Developers may designate a component within an application as the explicit testRoot. This component can then be referenced by the special root locator segment

    //testRoot[]

    This is useful for cases where a standard widget hierarchy may be dynamically rendered inside some component (such as a screen) - see the PortableAutoTests topic for more information

  • Base Search Segment: The AutoTest subsystem supports searching for components by a defining property value. If a target element is not a descendant of a component with an explicitly specified ID, and is also not contained within the specified testRoot for the application, but is contained within a component that has a specified definingProperty value, this may be used to identify the root component for the locator.

    Base search segments are prefixed with "//:" and include the class name for the target component along with the defining property value.

    For example - dataSource is a defining property for ListGrids. The following locator would identify a ListGrid bound to a dataSource with the ID "someDS" wherever it appeared in the page's widget hierarchy:

    //:ListGrid[dataSource="someDS"]

    AutoTest.getLocator() will only generate a locator with a base search segment if the defining property value would unambiguously identify the base component within the application. The above locator would not be generated in an app with more than one visible ListGrid bound to "someDS".

    Note that by default hidden and/or undrawn components are not considered when generating and resolving locator search segments, but the special "?" character indicates that both hidden and visible components must be considered when resolving a search segment.

    For example the locator //:?ListGrid[dataSource="someDS"] would retrieve a ListGrid bound to "someDS" whether visible or hidden.

    AutoTest.getLocator() will generate this locator format if the target element was hidden, or if passed the searchSegmentsIncludeHidden attribute of the settings argument.

Interior locator segments

In some cases a single segment may be sufficient to identify a target element or object on the page, but in most cases, the root component locator will be suffixed with a number of interior locator segments to identify the path from the root component to the target element.

The format of individual segments within a locator will be different for different widget hierarchies and target elements. Smart GWT does not exhaustively document every possible locator format for every widget, but the patterns used are consistent and can inform application design:

  • Named AutoChildren: Named autoChildren will be identified within their creator by their autoChild name - for example

    //Window[ID="mainWindow"]/body

    This happens regardless of the interim widget hierarchy between the creator and its auto-child.

  • Explicit locatorChildren: Components with an explicit named locator child relationship will be identified within their locator parent by name. For example marking a member of a Layout with the locator child name "myView" might produce a locator like:

    //VLayout[ID="mainLayout"]/myView

    Once again, this is regardless of the interim widget hierarchy between the locator parent and its locator-child.

  • Search Segments: Interior search segments in a locator are prefixed with "//". Interior search segments indicate that a component may be uniquely identified by a defining property value within the component identified by the previous segment in the locator.

    For example the following locator would search for a ListGrid bound to "someDS" within the body of a window with ID "mainWindow":

    //Window[ID="mainWindow"]/body//ListGrid[dataSource="someDS"]

    Note that the AutoTest.getLocator() method will never return a locator with a search segment that is ambiguous in the current application.

    If the AutoTest system can uniquely identify a component by defining property across the app as a whole, it will typically be used as a base search segment. If not the system will find the highest-level ancestor containing only one descendant with the specified definingProperty, and ensure the previous segment in the locator identifies that ancestor. This ensures that the final locator string is as compact as possible while unambiguously identifying the target.

    As with base search segments, a "?" character is used to indicate that hidden or undrawn components should be considered when resolving search locators. For example the following locator:

    //Window[ID="mainWindow"]/body//?ListGrid[dataSource="someDS"]

    would include hidden listGrids when searching for the grid bound to the specified dataSource.

  • Locator segment fallback attributes: If a target element or component cannot be identified within its parent by a simple identifier such as autoChildName or defining property, the AutoTest subsystem will generate a segment containing one or more attributes to identify the target. When multiple attributes are recorded it allows the Smart GWT framework to use several strategies to find the target. These additional locator segment attributes are referred to as "fallback attributes".

    For example a locator segment with a full set of fallback attributes identifying a member of a Layout might look like this:

    VLayout[ID="mainLayout"]/member[Class=TreeGrid||index=1||length=3||classIndex=0||classLength=1||roleIndex=0||roleLength=1||scRole=tree]/

    This specific segment indicates that the target component is a member of a layout. The target is a TreeGrid, and is the first of 3 members. It also indicates this is the only member TreeGrid in the members array [indicated by the classIndex and classLength attributes], and that it is the only member with role set to "tree".

    The parent layout will use these fallback attributes in the locator as necessary to find the appropriate member. If the layout has three members, and the first is a TreeGrid, the target may be resolved to this member with some confidence.

    If this is not the case, but there is exactly one TreeGrid in the members array, or exactly one element with role set to tree, it will fallback to those secondary locator strategies. If fallback locator strategies are used, a warning will be logged so developers are aware of any potentially incorrect locator parsing.

    Developers may influence how recorded locator attributes are resolved via properties on the locator parent. For Layouts this would include Layout.locateMembersBy and Layout.locateMembersType.

    For brevity and readability, when generating locators, developers may choose whether or not to include multiple fallback attributes in locator segments by setting useMinimalFallbackAttributes to false globally, or on the settings parameter passed to AutoTest.getLocator().

  • Component interior locators: Different Smart GWT components have their own patterns for identifying significant elements in the DOM within their handles. For example, ListGrid cell elements are located by row and column data. Where appropriate, properties to control how component-interior locators behave will be documented on the class in question.