Skip to main content

Jemmy Module - Tutorial

This tutorial below doesn't expose Jemmy functionality very much.
It mostly shows how to use the most hi-level jemmy part - operators.
It also provides some references to the lower-level functionality.
Table of Contents

Downloading
Test class creation
Application execution
Window searching
Component searching
Access to swing component
Actions with component
Nonblocking actions
Event queue using
Jemmy exceptions
String resources
Timeouts
Drivers
Robot vs event dispatching.
Timeouts and resources location.
Test execution.
Test stability.

See also: all samples, Applet testing tips.


Downloading

First, you have to download jemmy.jar


Builing

If you have Jemmy sources, simply tin ant, while being in the root dir of Jemmy distribution.
Getting samples

You could get the samples from here.
Compiling samples

Go to where your sumples are and un javac -classpath <jemmy classes or jar> <sample name>.java.
Try it now with WaitWindowSample. <sample name>.class should be created in the current dir.
Sample execution

Just to try whether things work, try to compile and run one test. While staying in the dir where compiled sample resides, run java -classpath <jemmy classes or jar>:<current directory> <sample name>.
You, of course, need to use ";" separator if you're on M$ Windows.
Try it now with WaitWindowSample. You should see a windows appearing and disappearing on the screen quickly. This is fine - the test worked.
All Samples use GUIBrowser UI, which is a part of Jemmy itself.
Test class creation

As it is repeatedly pointed out, Jemmy is not a test harness, hence, it does not provide a complicated test execution engine.

As Jemmy is a java-library, you could, of course, use the Jemmy classes from any Java class. For the tutorial purposes, though, we will use implementation of org.netbeans.jemmy.Scenario interface. The public int org.netbeans.jemmy.Test.runIt(Object) method is the test scenario.
Examples: WaitWindowSample.java or any other sample


Application execution

To test a Java UI applicatio, you should first execute it. Jemmy test must be executed in the same JVM as the tested application is executed in. The easiest way to do it is to run the application's main method from test. It could , optionally, be done through reflection. There is an org.netbeans.jemmy.ClassReference class which makes it easier.
Examples: WaitWindowSample.java or any other sample

Note:
ClassReference class using allows to avoid application classes import.

Note:
Application may be able to run test from itself. In that case you have to decide yourself way is better for you.


Window searching

To do anything with swing component, you have to find it first. To find component you first have to find a window containing it.

Note:
Java UI application is an multi-thread application itself. The test thread is, yet another thread. That said, "finding" does not make much sense. Instead, Jemmy always "waits" for the desired state to be reashed. So below when we really mean "wait" we say "find."
Low-level functionality is implemented in org.netbeans.jemmy.ComponentChooser and org.netbeans.jemmy.WindowWaiter classes.

The most typical scenario is finding a frame or dialog by title. Both org.netbeans.jemmy.operators.JFrameOperator and org.netbeans.jemmy.operators.JDialogOperator have constructors with java.lang.String parameter which allow to find a frame or dialog. Dialog also can be found between its parent children if we know the parent.

Note:
Jemmy provides much more searching capabilities than just be the title. Check Javadoc to find out more.
Examples: WaitWindowSample.java, WaitDialogSample.java


Component searching

As soon as we have found a window, we have a starting point to find a component. Components can be searched inside the container. org.netbeans.jemmy.operators.ComponentOperator and all its subclasses (except operators for window-like components, like popups) have constructors with org.netbeans.jemmy.operators.ContainerOperator parameter. The rest of the parameters differ from component to component. Most operators have constructors with java.lang.String parameter which defines a component string resource value.

Examples: FindComponentsSample.java

Note:
Components also can be found by an ordinal index or by a string and an index. The way to compare strings during searching:
org.netbeans.jemmy.operator.Operator.StringComparator
org.netbeans.jemmy.operator.Operator.setDefaultStringComparator(org.netbeans.jemmy.operator.Operator.StringComparator)
org.netbeans.jemmy.operator.Operator.setComparator(org.netbeans.jemmy.operator.Operator.StringComparator)


Access to swing component

Having an operator, you can get a component by org.netbeans.jemmy.operators.ComponentOperator.getSource() method. But, all operators map all components methods: org.netbeans.jemmy.operators.AbstractButtonOperator.getText() maps javax.swing.AbstractButton.getText(). The difference between ((AbstractButton)abstractButtonOperator.getSource()).getText() and abstractButtonOperator.getText() is that an operator invokes getText() through the event queue. So, normally it's better to use an operator's methods to access components. It gives more test stability.

Note:
Operator's mapping method cannot be used if the code itself is executed inside the queue. Using an operator's mapping method will result in a deadlock in this case.
Note:
Behavior described above is used by default. You can, though, change it. See Event queue using for more info.


Actions with component

org.netbeans.jemmy.operators.ComponentOperator contains all methods simulating user input by mouse and keyboard operations. Other operators contain most methods necessary to drive components.

Examples: ActionsSample.java, TreeActionsSample.java, TableActionsSample.java


Nonblocking actions

This section applies to non-robot mode only. Robot operations work well when either any modal dialogs are displayed or not.

If a modal dialog is shown as a result of an action (such as button pushing), the push method will never end and thus, test execution will be blocked. In this case, one of the nonblocking methods have to be used:
org.netbeans.jemmy.operators.AbstractButtonOperator.pushNoBlock()
org.netbeans.jemmy.operators.AbstractButtonOperator.changeSelectionNoBlock(boolean)
org.netbeans.jemmy.operators.JMenuBarOperator.pushMenuNoBlock(ComponentChooser[])
org.netbeans.jemmy.operators.JMenuBarOperator.pushMenuNoBlock(String[])
org.netbeans.jemmy.operators.JMenuBarOperator.pushMenuNoBlock(String path, String delim)
org.netbeans.jemmy.operators.JMenuOperator.pushMenuNoBlock(ComponentChooser[])
org.netbeans.jemmy.operators.JMenuOperator.pushMenuNoBlock(String[])
org.netbeans.jemmy.operators.JMenuOperator.pushMenuNoBlock(String, String)
org.netbeans.jemmy.operators.JPopupMenuOperator.pushMenuNoBlock(ComponentChooser[])
org.netbeans.jemmy.operators.JPopupMenuOperator.pushMenuNoBlock(String[])
org.netbeans.jemmy.operators.JPopupMenuOperator.pushMenuNoBlock(String, String)

Examples: WaitDialogSample.java, Note:
Indeed, any blocking action should be just executed in a separate thread. So if you have a testcase where a modal dialog is shown, but Jemmy does not provide such kind of nonblocking operation, you will have to create the thread yourself. Either way is good, but we recommend to override the org.netbeans.jemmy.operators.Operator.NoBlockingAction class and run it using the org.netbeans.jemmy.operators.Operator.produceNoBlocking(NoBlockingAction,Object) or the org.netbeans.jemmy.operators.Operator.produceNoBlocking(NoBlockingAction) method.


Using the Event queue

Since all GUI updates normally go though the event queue, it can be used for the test stabilization purpose. Read "EventQueue using" for more information.

Example: QueueUsingSample.java

Note:
If, during execution, the application does not update its GUI periodicially, then the GUI may only change after some user input. So, if the queue is empty, we can be sure that user input has been processed completely, and thus, we can post other input operations. If the application does run something, we cannot be sure of this.
Note:
org.netbeans.jemmy.QueueTool class provides some more functionality such as wait for the queue be staying empty during certain time.


Jemmy exceptions

Any unsuccessful operation in Jemmy exits with an exception. All exception classes extend org.netbeans.jemmy.JemmyException.

Note:
Here's a tip on how to use Jemmy functionality in a negative way. You could insert an operation which shouldn't work in a try-catch block.


String resources

String resources like button text, window titles, tree paths, ... could be moved into special resource files.
It saves you from changing all the tests in case just the application's window title was changed. Also it requires just one set of tests for all languages supported by the application.
Examples:
ResourceSample.java, resourcesample.txt

You can load resources from a file by using the org.netbeans.jemmy.Bundle.loadFromFile(String) method.

Note:
Implementation is in two classes: org.netbeans.jemmy.Bundle and org.netbeans.jemmy.BundleManager


Drivers

This is definitely low-level functionality, and normally it's not something test developer should take care about.

Starting from Jemmy 2.0 operators behavior is defined by a set of classes called "drivers" (org.netbeans.jemmy.drivers package).

For instance, button puching is performed by ButtonDriver implementation, which has press, release and push methods. The implementation could do pushing using mouse, keyboard, or just invoke AbstractButton.doClick() method.

By default Jemmy uses a set of drivers allowing it to work exactly the same way Jemmy 1.0 working.

Practically, depending on you specific system requarements you might want to change some of the existing drivers to perform user actions reproducing model. You can even create you own drivers - just implement one of the *Driver interfaces and register you driver by one of the DriverManager methods.

Do this registration before any other test action so all the created operators will use registered drivers.


Timeouts

All GUI operations take time, so a test running in it's own thread, mostly waits for something to happen.
Jemmy has a lot of timeouts for different types of waiting. All timeouts used by a class are usually described in javadoc (you can see them in the class' page title).

Note:
If waiting was not finished successfully in an appropriate time, org.netbeans.jemmy.TimeoutExpiredException will be thrown.

There also is another type of timeout - sleeping timeouts. For different purposes (like demo or test debugging) it's useful sometimes to increase them.
Default values for all sleeping timeouts are 0, except Waiter.TimeDelta (see below)
Examples of timeouts:
ComponentOperator.PushKeyTimeout - time to sleep between key pressing and releasing.
Waiter.TimeDelta - default time to sleep between attempts.
WindowWaiter.WaitWindowTimeout - maximum time to wait window.
JTreeOperator.WaitNodeExpandedTimeout - maximum time to wait next node loaded during tree operations

Timeouts values can be stored in file in properties format:
Waiter.TimeDelta=1
WindowWaiter.WaitWindowTimeout=180000
        
You can load them using the org.netbeans.jemmy.Timeouts.load(String) method.


Robot vs event dispatching

Starting from 1.3, Java has included the java.awt.Robot class which generates native system input events for the purposes of test automation. Jemmy test can be executed using Robot, as well as without. In the second case, Jemmy dispatches events directly to components working with.
So, what's the difference?
Obviously, Robot mode is more "honest". If something cannot be done manually, it cannot be done automatically. This gives us a certainty the only tests that passed are the ones that can be reproduced manually. And there is no such thing as, what cannot be done by robot mode can only be done manually.
On the other hand, "dispatching" mode does not care about any window could be opened by the window manager even if it completely closes the application's windows. It can work on locked display (it depends on operating system and window manager). It is also a little faster. Finally, it is way more stable. See more onn this.
"Dispatching" mode is used by default. You can change it this way:
JemmyProperties.setCurrentDispatchingMode(JemmyProperties.ROBOT_MODEL_MASK)
Or from command line:
java ... -Djemmy.robot_dispatching=on ...


Timeouts and resources location.

Jemmy recognize one more option from command line: jemmy.properties. Value of this option must be file name containing two (or just one of them) strings:
TIMEOUTS_FILE=[file containing timeouts]
RESOURCE_FILE=[file containing string resources]
        
These string defines files to load timeouts and string resources resources from.


Test stability

GUI tests are unstable - that's a reality.
Imagine if the network was very busy when a test was waiting for the window which loads something through the network during creation.
How long should the test wait for the window? How soon the test should give up?
We have a choice here.
We can set the window waiting timeout awfully long. In this case, the testsuite won't completely pass because of an application or test bug in the very first test.
Or we can use some reasonable value and check test failures after each testsuite execution.
It's up to you which way to choose. It depends on a lot of things: how big your testsuite is, how stable application design is and so on.

Note:
Jemmy provides some useful APIs to find the cause for a failure. It is: org.netbeans.jemmy.util.Dumper class which dumps information about all displayed components into a file in XML format. And the org.netbeans.jemmy.util.PNGEncoder class grabs information from the screen and puts it into a PNG image file.

Test execution

In the real live, you will, likely, be executing tests by some test harness (such as JUnit), which provides execution of a list of test, test monitoring, tests result formatting, and so on. Use your harness documentation to find out how to organize your tests.


 
 
Close
loading
Please Confirm
Close