JavaSwing Reference 2.1
Aus ExpeccoWiki
This is the JavaSwing-Plugin documentation for expecco version 2.1.
This expecco plugin provides facilities to automate tests incorporating Java AWT/SWING applications. It also lets you access GUI components and other objects of a running Java Application, and to use and validate them in a test. In addition to single JavaSwing application tests, more advanced end-to-end scenarios are possible, where complex setups involving multiple Java-Swing apps, web-services, hardware and even mobile devices even combined can be controlled and tested from a single expecco test description.
Inhaltsverzeichnis |
Features
- Automated GUI testing of Java AWT/SWING applications
- Parallel remote test-execution on multiple systems
- Performs tests against completely built and executable Java applications. No source code changes / recompilation of the application is required
- Access GUI components, using XPath-like locators.
- Access Java objects of the application live at execution time. See JavaBridge Interface Library for more details about runtime object and Java VM access
- Consists of an expecco block library and tools which help to model tests and inspect the GUI of the application
Installation
The JavaSwing testing plugin uses a so called "Java-Bridge" which consists of two parts: one side is a plugin for expecco, the other side is an extension to the Java execution environment (the "JavaBridgeAgent"). Expecco uses that bridge to communicate with the tested JavaSwing application.
Requirements and Important Update Notes
In the last version, the agent was loaded by Java's assistive technology loader. For this purpose the JRE was modifyed with some files. These changes must be undone. Use the JavaBridgeAgent uninstaller (if installed with JavaBridgeAgent setup) or remove the files by hand. Remove "JRE_HOME/lib/ext/JavaBridgeAgent.jar" and undo the changes in the "JRE_HOME/lib/accessibility.properties" file. See "Setting up the JavaBridgeAgent" in the old documentation for more details.
The new startup process is using Java's attach API. So a Java Development Kit(JDK) is required. The application to test can still be executed in a normal Java Runtime Edition(JRE). The JDK is only used to attach into a running Java Virtual Machine.
Requirements
On the test executing machine.
- A Java Development Kit 1.6 or higher (for startup)
- A Java Runtime Edition 1.6 or higher (executing the application to test)
Installing the Plugin in Expecco
The plugin is usually installed automatically by the installer; either included in the main expecco installation or provided as a separate installable add-on package. Its files are stored in the "plugin" subfolder of the expecco installation folder. You can also copy those files manually to that folder, if required. Expecco detects the plugin automatically during startup. So it may be required to restart any expecco session.
After starting expecco open the expecco settings by navigationg to "Extras->Settings->Plugins->JavaSwing". Enter the Path to the Java Development Kit (Commonly somehting like "C:\Program Files\Java\jdk1.7.0" on windows). Then Save the settings.
Plugin Components
The bridge plugin consists of the following parts:
- The Awt/Swing-browser, is used to explore your application.
- The JavaSwingLibrary, provides blocks that you can use in your test-cases.
- The JavaBridgeAgent, provides the interface between the tested application and your tests (i.e. expecco).
AWT/Swing-Browser
The AWT/Swing-Browser is a tool to explore the component tree(s) of one or multiple currently executing Java application(s). It helps to explore the application and to develop your tests.
Starting the Browser
Navigate to the menu "Plugins->Gui Testing->Open Browser" to open the Gui Browser. This browser handles multiple connections to multiple applications. It displays a component "'forest", consisting of one component-tree per connected application.
Starting the Agent and Connecting to the Application
To connect to your application, the application to test must be running and the agent must be loaded into the same Java VM.
Starting the Agent Local or Remote
For local running applications, the agent will be loaded automatic during the connect, both using the Browser or the connect block. For remote connections, the agent must be started by commandline or script.
- Copy following files from the expecco javaSwing plugin directory. (<Your expecco installation>/plugin/javaSwing)
- "./agentLoader/systemDLL/AgentLoader.jar" to <any folder>
- "./agentLoader/systemDLL/JavaBridgeAgent.jar" to <any folder>
- "./agentLoader/systemDLL/lib/jaccess.jar" to "<any folder>/lib"
- Move your <any folder> to your remote machine.
- On your remote machine open a command and switch to <your folder>
- Execute following command:
"<jdk_home>/bin/java" -classpath .;"<your folder>/AgentLoader.jar";"<jdk_home>/lib/tools.jar" exept.expecco.agentloader.AgentLoader" <port>
port - is the port number where the agent will be listen for connections.
Connecting to the Agent
Select "Browser"->"Connect with..."->"Java Application" to open the connect dialog.
Enter the address of the host on which the tested application is running. The host address can be either the host-name or the IP-address.
Host - The target host name or its IP-address.
Port - The port on which the attached agent is listening.
After the connection has been established, the component tree of all running applications on the target host is shown.
For each application, one subtree which starts at the top level window of each application is shown. The tree elements show a component's role followed by its name and value (if the component has a name or value). Select a component and press the right mouse button to open a context menu. The context menu performs its operations on the selected component(s).
Browser functions
The most functions ar available via the context menu by selekting an element in the tree and pressing the right mouse button.
Follow Cursor
- Select the menu-item "Operations"->"Follow Cursor" to toggle the "follow-cursor" mode. If that mode is enabled, the browser's selection will follow the component under the mouse-pointer. If required, the tree will expand and/or scroll to make that component visible. Use this to find components in the browser tree, for which no locator is known (i.e. if the application is unknown/undocumented).
Start Recording
- Selected from the context menu, a recording session is started which only records for elements of the same application as the selected element in the tree. The recording button on the tool bar will start a recording session for all connected applications.
Verify Path
- Use this function to optimize (i.e. shorten) a locator path. You can try alternative pathes and check if the new path still matches and returns the same component. To use this function, select a component in the browser's tree and select the "Verify Path" menu item in the context menu.
- You can modify the path in the input field and try alternative (shorter) pathes.
- Verify Path
- Verifies the path and displays information about the component matched by this path.
- Reload Path
- Reset and display the absolute path of the selected component.
- Copy Path
- Copy's the path to the clipboard.
- Result View
- Displays detail information about the located component. "Receiver:" is the component itself, "Children" are its direct descendends.
Actions
- To display a component's actions, right-click and select the "Actions" item. Components which do have actions are marked by a blue "A" in the tree. To execute an action, select any from the shown list-of-actions and press "Execute".
Selection
- If a component has selection capabilities, it is marked in the tree with a blue "S". RIght click and select "Selection" in the context menu.
- In the selection screen, you see the currently selected indices and some information about them.
- Select All
- This selects all indices.
- Clear All
- Clears the selections.
- Update
- Shows the currently selected indices.
- Add Indices
- In the text input, enter indices separated by ",". Click on "Add Indices" to have them selected.
- Remove Indices
- Similar to "add indices", but removes the specified indices from the selection.
Table
- Components with table functionality are marked with a blue "T" at the end in the tree. Right click and select "Table" from the context menu.
- In the table screen, you see more detail information about a single row. To iterate through the rows, use the arrow buttons.
- Get Header
- Displays the header of the table.
- Get Row At
- Displays the specified row. To specify a row, enter the row's index into the input field to the right of the "Get Row At" button.
Text
- Components with text are shown with a blue "T" at the second position in the tree. To see the text screen, select the component in the tree, and select the "Text" item from the context menu.
- In the text screen, you can view and edit the text-contents of a component.
- Get
- This gets the currently displayed text of the component.
- Set
- To change the text of the component. To modify the text, edit the text in the input field.
Details
- Details shows more information about a selected component. You see the "role", "name", "index" in parent, "bounds", "access" options, the current "states" and the "image path" of a component.
Grab Widget
- This function captures a snapshot-image of the component's rendered contents. "Grab Widget" is useful to see what is currently displayed at a remote target host, and/or to fetch an image to be used in the text.
- To see a component's currently rendered contents, select it in the browser tree and select "Grab Widget" from the right-button menu.
Mouse Events
- In the mouse event screen, you can send simulated mouse & mouse-movement events to a component. To open it, select a component from the tree and then select the "Mouse Events" conetxt menu function.
- Button
- Select the mouse button you want to press.
- Offset X and Y
- The offset (in pixels) of the click position. The click position is relative to the upper left corner of the selected component. You can give both positive and negative values as offset.
- Request focus
- Sets the focus to the component.
- Move mouse to position
- This moves the mouse pointer to the position relative to the upper left corner of the selected component.
- Press button
- Moves the mouse pointer to a position and simulates a "press event" for the specified button.
- Release button
- Similar to "press button", but simulates a "release event".
- Single click
- Simulates a press and release in sequence.
- Double click
- Simulates two single clicks which are performed within a short time.
Element-Path
The Element-Path is a notation to describe the access-path to a component within the component tree of a Java Awt/Swing application. It is similar to XPath, as used in DOM-tree locators for web applications. An element's path can be retrieved via the AWT/Swing-Browser . In the test's action blocks, the component's path is used to specify its location (very similar how DOM elements are located in a web-test scenario). A path can contain dynamic parts and needs not to be absolute.
Note: The component tree might change during the execution of the application. For example, when a popup menu opens, the tree could be extended by dynamic menu-components and the path might change. In this case, use dynamic parts in the path or a path as retrieved when the popup menu was shown.
Specifying Paths
A typical path looks like:
/frame[@name='Notepad']/root pane/layered pane/panel/panel/panel/tool bar/push button[2]
This example describes the path to a tool bar, where the second button is selected. This is an absolute path.
The path is specified as a list of component identifiers. Each component identifier starts with a "/". A component identifier represents a node in the component tree. "/frame[@name='Notepad']" is the first component identifier for a JFrame. "/root pane" is the second component identifier and so on. The path is resolved by matching the children of a component against the current component identifier. In the example above, "frame" has one or more children. One of them is matching the "root pane". Again, "root pane" has one ore more children and one of them matches against the "layered pane" component identifier and so on.
The syntax of a component identifier is:
/<nodeIdentifier><[optional selector]>
Node Identifiers
The node identifier specifies which kind of component to look for at the current component tree position.
Available identifiers:
- The role of the component.
- This results in one or more components matching the role of the components; for example, "push-button" for a button.
- The "*" which matches any component
- Match the rest of the path against all child components at the current tree position.
Examples:
- Absolute path:
"/frame[@name='Notepad']/root pane/layered pane/panel/panel/panel/tool bar/push button[2]" - The same path with any components:
"/*[@name='Notepad']/*/layered pane/panel/panel/panel/*/*[2]"
These two pathes will locate the same component in the previous example.
Selector (Index/Name)
The selector is optional and required to select an element from a locator where multiple components match. For example, if you have a panel with 3 buttons in it, you have to specify which of the 3 buttons to locate using a selector. The selector is enclosed in "[" and "]". The selector is resolved against the result of the node identifier match. This means if you have a component with two buttons and two combo boxes, and your identifier is the role pushbutton, then the selector is matched against the list of the two buttons.
Available selectors:
- The index selector
- Selects the component by its position in the match list. The syntax is "[index]", where index is one-based (1..)
- The @name selector
- Selects the component by its name. The syntax is "@name='<the name here>"
Examples:
//tool bar/push button[2]
- Assuming that the tool bar contains at least two buttons, the second button is selected.
//tool bar/push button[@name='Save As...']
- Again the second button is selected, here by its name.
Special Wildcard Notation
The // wildcard notation can be used to make a path much shorter and more flexible (also required, if dynamic component pathes exist). The "//" matches parts of the path and stands for "any sub path". As such, it can be seen like a super "*"-matcher: not only does it match single components along the path, but any sequence of arbitrary components is matched by it.
Example: Assuming that the full path to a "push-button"-component is:
/frame[@name='Notepad']/root pane/layered pane/panel/panel/panel/tool bar/push button[@name='Save As...']
If the application has only one button with the name "Save As...", it can be shortened to:
//push button[@name='Save As...']
If there is only one component with the name "Save As...", you can even write:
//*[@name='Save As...']
Alternatively, you replace only some parts of the path with this wildcard like this:
/*[@name='Notepad']//panel//tool bar/*[@name='Save As...']
Note:
Use a path as short as possible, to allow for freedom with respect to changes in the layout. For example, the above shortened locators are more robust against added frames or other geometry changes in the application than the full path. However, be aware that it also increases the chances for multiple components to match the locator - and thereby also breaking your test. Some heuristics and experience is helpful in choosing a good locator.
JavaSwingLibrary
With the operations described above you can explore a running Java Swing application. For automation and testing of an application, a library of building blocks is provided, which contains functional blocks for all of those operations.
The JavaSwing Library consists of a set of predefined function blocks which are used to model your tests. Import this library via expecco's "Import Library" menu-function.
Predefined blocks
Importand Update Notes
In the previous librarys, nearly each block had have a bridgeID pin. This has been removed. The old blocks have been moved to the obsolete group.
Initialization (obsolete)
- Setup Locator
- A locator is an alias for a path to a component. It can be used to shorten the path expressions. Each locator will be expanded in a path expession.
- identifier <String> - The identifier for your locator.
- path <String> - The path to the component.
- To use an locator as at a path input, write "@<your locator identifier here>". You also can use the locator as path part like this: "@<your locator identifier here><the rest of your path>".
- Example: Use "@MyTabPaneLocator/page tab list[@name='Simple Widgets']/..." as path input.
- Raise Window
- Brings a window to the front by specifying a path to a component which is contained in the window.
- path <String> - The path to the window or to one of its containing components.
- Example: For a window path, write "/frame[@name='Notepad']" or "/frame" if it only has one window. Or use a path to one of the components of the window, like "//push button[@name='Save As...']".
Connection
- connect to host
- Establish a connection to a target host by its network address.
- host <String> - The IP-network address or host name of the host you want to connect to. The default TCP port 4712 is used.
- connect to host on port
- Establish a connection to a target host by its network address and TCP-port.
- host <String> - he IP-network address or host name of the host you want to connect to.
- port <Integer> - The TCP port to use for the connection.
Actions
- execute action
- Execute an action on a component.
- path <String> - The path to the component on which to perform the action.
- action <String> - The action to perform.
Mouse trigger
- move mouse
- Move the mouse pointer on the screen to a position relative to the upper left corner of a given component.
- path <String> - The path of the component where the pointer is moved to.
- Optional: offsetX as Integer - A positive or negative offset which is added to the x coordinate of the upper left point of the component on the screen.
- Optional: offsetY as Integer - A positive or negative offset which is added to the y coordinate of the upper left point of the component.
- move & click left button
- Move the mouse pointer on the screen to a position relative to the upper left corner of a given component and then performs a mouse click with the left mouse button at that position.
- path <String> - The path of the component where the pointer is moved to.
- Optional: offsetX as Integer - A positive or negative offset which is added to the x coordinate of the upper left point of the component on the screen.
- Optional: offsetY as Integer - A positive or negative offset which is added to the y coordinate of the upper left point of the component.
Selection
- select all
- If the component supports selections, select all the items of the component. For example, if the component is a list which allows multiple items to be selected, then all the items of the list will be selected.
- path <String> - The path of the component whose elements should be selected.
- get selected indices
- If the component supports selections, this will return a collection of indices of the currently selected items of a component. If nothing is selected, an empty collection will be returned.
- path <String> - The path of the component where to look for the selected items.
- Returns: indices <OrderedCollection of Integers> - an empty collection is returned if nothing is selected. Otherwise the collection contains the indices of the currently selected items.
- select index
- If the component supports selections, the item at the given index is added to the current selection.
- path <String> - The path of the component where to select the item.
- index <Number> - The item index which should be added to the selection.
- clear selection
- De-selects all the selected items of a component.
- path <String> - The path of the component whose selection should be cleared.
Setup Entry Fields (Text,Numbers ...)
- set text
- Set the text of a text component to the given text.
- path <String> - The path of the text component where to set the text.
- contents <String> - The text to set.
- get text
- Return the text of a text component.
- path <String> - The path of the text component where to get the text from.
- Returns: contents <String> - The text at the text component.
- get value
- Return the value of a component which provides a value. For example a progress bar will return its progress value.
- path <String> - The path of the component where to get the value from.
- Returns: currentValue <String> - The current value of the component.
Verification
- VerifyPath
- Check if the specified path addresses a component.
- path <String> - The path that should be verified.
- Returns: PathExists <Boolean> - Return true, if a component is found at the path, false otherwise.
- get states
- Return the current states of a component.
- path <String> - The path of component where to get the states from.
- Returns: states <Collection of Strings> - a list of the current states of the component.
Table
- get row (cells)
- Return the names of the cells in a table row.
- path <String> - The path of table component where to get the row from.
- rowIndex <Integer> - The row index where to get the cells from.
- Returns: values <StringCollection> - A list of cell names.
- get number of table rows / columns
- Return the number of columns and rows of a table component.
- path <String> - The path of the table component, whose column and row count should be returned.
- Returns:
numberOfColumns <Integer> - The number of columns in the table.
numberOfRows <Integer> - The number of rows in the table.
- Returns:
Accessing Java Objects
You can interact with the Java objects as described at JavaBridge Interface Library. To get the Java proxy object by the path of a component you can use following code.
javaObject := JavaSwing::JavaSwingAgentManager getJObjectForPath:'//text'.
Replace '//text' by the path of one of your component. This will return a Java proxy object which can be used as described at JavaBridge Interface Library.
Example
This is an example from a small notepad application which performs an undo by using the menu bar.
The network to do that could look like this. (Old blocks with bridgeID used in this example, new blocks will not have a bridgeID pin)
The first Step will open the "Edit" menu by a mouse click. Next "Undo" will be clicked. Then the text of the component which contains the text is retrieved. The retrieved text will be compared to the text "Hello JavaSwing". If the text matches each other, the test will be passed otherwise the test will be marked as failed.
Back to Online Documentation.