Writing JellyTools Tests Guide

Author: Alexandre Iline, Jiri Skrivanek
Last update: May 13, 2011



This document describes how to write GUI tests for NetBeans IDE using the JellyTools library. JellyTools contains classes to cover most of the functionality necessary to work with NetBeans IDE core GUI components and windows.

See Writing_JellyTools_Operators_Guide for instructions how to create classes covering non-core (i.e. module specific) NetBeans GUI parts.

JellyTools is based on the Jemmy library. JellyTools provides direct access to Jemmy functionality, so you can use Jemmy in your tests directly. (See more info about using Jemmy below). However, it is highly recommended to put as much functionality as possible into module specific operators.

To demonstrate Jellytools operators we prepared several examples which will be used in this document.

How to execute tests

UI tests based on Jellytools can work only if they are executed in the same JVM as the tested application. In order to fulfill this requirement you need to use NbModuleSuite while defining your test suite. Steps to run JellyTools examples are as follows:

  • run NetBeans IDE
  • open jellytools.java project from NetBeans repository
  • find examples package under Functional Test Packages
  • open any test class in editor
  • use Run File (Shift+F6) or Test File (Ctrl+F6) action
  • alternatively you can toggle breakpoint somewhere inside test class and use Debug File (Ctrl+Shift+F5) or Debug Test File (Ctrl+Shift+F6) action

How to create tests

Tests are based on the JUnit framework. We recommend using JellyTestCase as a superclass. It performs necessary Jemmy initialization and handles test case exceptions.


import java.util.logging.Level;
import junit.framework.Test;
import org.netbeans.jellytools.JellyTestCase;
import org.netbeans.junit.NbModuleSuite;

/** It is just an example how test could look like. */
public class EmptyTest extends JellyTestCase {

    /** Constructor required by JUnit */
    public EmptyTest(String testName) {

    /** Creates suite from particular test cases. */
    public static Test suite() {
        // run tests in particular order
        //return createModuleTest(EmptyTest.class, "test2", "test1");

        // run all tests 
        //return createModuleTest(EmptyTest.class);

        // run tests with specific configuration
        NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(EmptyTest.class).
        conf = conf.addTest("test1");
        return NbModuleSuite.create(conf);

    /** Method called before each test case. */
    public void setUp() {
        System.out.println("########  " + getName() + "  #######");

    /** Method called after each test case. */
    public void tearDown() {

    /** Test case 1. */
    public void test1() {
        System.out.println("test case 1");

    /** Test case 2. */
    public void test2() {
        System.out.println("test case 2");

This test does not really do anything - working code should be in the test1(), test2() methods.

To get various ideas you can also take a look at JellyTools internal tests placed under Functional Test Packages folder in jellytools.* projects in NetBeans repository.


JellyTestCase is an extension of NbTestCase. It is intended for NetBeans GUI testing explicitly.

JellyTestCase initializes Jemmy. Contents of that initialization can be changed at any time. For now, it initializes output so test output is really going to a log provided by NbTestCase and sets some timeouts necessary for NetBeans GUI testing.

Any JemmyException (which is normally thrown as a result of an unsuccessful operation in Jemmy) going from a test is treated by JellyTestCase as a test failure; any other exception - as a test error.

Using its public switches you can define whether a test should

  • close all modal dialogs at the end of the test case (switch jemmy.close.modal - default true)
  • generate component dump (XML file containing components information) in case of test failure (switch jemmy.screen.xmldump - default false)
  • capture screen into a PNG file in case of test failure (switch jemmy.screen.capture - default true)
  • wait at least 1000 ms between test cases (switch jelly.wait.no.event - default true)

What to use

JellyTools classes could be divided into five structural parts:


Jemmy operators are a set of classes which are test-side agents for application components. Operators provide all possible methods simulating user action with components, methods to find and wait components and windows. Also operators map all components methods through the event queue used for event dispatching. All JellyTools operators are subclasses of Jemmy operators.

All of the operators provide access to their sub components by "getters" methods. These methods are implemented using the "lazy initialization" technique, so real sub operator instances are not initialized until it is necessary. All of the sub operators are initialized by verify() method invocation, so this method guarantees that all sub components are already loaded.

Getters' method names usually have a prefix showing component type, the rest of the names usually repeat component text or text of the corresponded label: JButtonOperator btCancel(), JRadioButtonOperator rbSubString(), JTextFieldOperator txtName(). You can see a full list of prefixes in a table shown in the Writing Operators Guide.

Some of the operators have an invoke() method which causes that component is opened via corresponding action. You can use these actions directly - their names usually look like *ViewAction (FilesViewAction for FilesTabOperator).

Most common JellyTools operators:

  • TopComponentOperator - is an operator for org.openide.windows.TopComponent component. It represents all dockable views in the IDE like Projects view, Editor views and others. TopComponentOperator can be used where no special operator like ProjectsTabOperator is not implemented.
  • NbDialogOperator - is the common superclass for all dialog operators in Jelly. It has some common methods for pushing the most used buttons on dialogs: "OK", "Cancel", "Close", "Help", "Yes", "No".
  • MainWindowOperator - handles the NetBeans main window. It manipulates with toolbars and you can get text from the status bar.
  • ProjectsTabOperator, FilesTabOperator, FavoritesOperator, RuntimeTabOperator - specialized TopComponentOperators for tabs in the IDE
  • EditorOperator- handles an editor top component in the NetBeans IDE. It enables you to get, select, insert or delete text, move caret, work with annotations and with toolbar buttons.
  • OutputTabOperator - operator to get text from the output tab.

Look at OperatorsTest.java file.


Action classes mission is to provide menu and popup calls.

Most of the actions inside the NetBeans IDE could be done in some different modes. org.netbeans.jellytools.actions.Action class is designed to describe all the modes in which the action could be performed:

  • by menu
  • by popup
  • by shortcut
  • by direct API call

Not all of the actions can be performed by all modes above, however, most of the menu/popup operations in NetBeans can also be done by shortcuts and direct API calls. Keeping that in mind, try to use a properly created Action instance whenever you want to perform menu or popup operations. Even if you do care to perform the operation exactly by menu (popup), create an action. The very same code could be used in a different place in another mode.

Using the perform() method of any action will perform the action by the first available mode that could be performed. The sequence of modes to be tried is defined by the Action.setDefaultMode(int) value.

Example (from ActionsTest.java):

       // create copy action
       CopyAction copyAction = new CopyAction();
       // call Copy popup menu item on the node 

Example above is performed in default mode. Copy action can also be performed in any of the other available modes.

Example (from ActionsTest.java):

       // perform action in different modes on a node

Actions can also be performed on a node, array of nodes, and ComponentOperator. If the action is performed on a node (nodes), node is selected first.

Action classes are in the org.netbeans.jellytools.actions package and module specific in org.netbeans.jellytools.modules.<modulename>.actions packages.


Node objects are designed to make tree operations easier. Node encapsulates information about the tree it's displayed in and about the tree path. Node classes can be used to perform applicable operations to the nodes in any tree in the IDE. Nodes can also be passed into Action.perform*(Node) methods.

There are some useful node types defined in JellyTools, such as: JavaNode, FolderNode, ProjectRootNode.

Example (from NodesTest.java):

       ProjectsTabOperator pto = new ProjectsTabOperator();
       // find node in given tree
       Node node = new Node(pto.tree(), "SampleProject|Source Packages|sample1");
       // find node under given parent node
       Node node1 = new Node(node, "SampleClass1.java");
       // select node
       // create instance of specialized JavaNode
       JavaNode javaNode = new JavaNode(node, "SampleClass1.java");
       // call predefined action

Nodes classes are in the org.netbeans.jellytools.nodes package and org.netbeans.jellytools.modules.<modulename>.nodes packages.


org.netbeans.jellytools.properties package contains classes to work with properties. Besides PropertySheetOperator, it contains classes - inheritors of org.netbeans.jellytools.properties.Property class.

Property value can be changed by inline editors (text field for string values, check box for boolean values - setValue(String) method and combo box for list values - setValue(int) method.

Example (from PropertiesTest.java):

       // open property sheet
       new PropertiesAction().perform(node);
       // find property sheet with given title
       PropertySheetOperator pso = new PropertySheetOperator("mykey");
       // find property Value
       Property p = new Property(pso, "Value");
       // get name and value
       System.out.println("PROPERTY: "+p.getName()+"="+p.getValue());
       // set new value
       p.setValue("new value");

Any property may or may not have a "..." button invoking a property editor. If a property has this button, it can have any number of set*Value(*) methods using the editor for property editing.

Some properties might be not editable directly (other than by the property editor). They extend Property and override setValue(*) methods to use the property editor. But if a property is editable directly, which most of them are, setValue(*) methods work directly.

Property editors are another class of operators which are located inside the org.netbeans.jellytools.properties.editors package and org.netbeans.jellytools.modules.<modulename>properties.editors packages.

Examples of property editors are: ColorCustomEditorOperator, DimensionCustomEditorOperator, FileCustomEditorOperator, PointCustomEditorOperator, StringCustomEditorOperator.

Property editor can be invoked by the Property.openEditor() method.

Example (from PropertiesTest.java):

       // open custom editor for property (...)
       // find custom editor
       StringCustomEditorOperator customEditor = new StringCustomEditorOperator("Value");
       // get value from custom editor
       // set value
       customEditor.setStringValue("new value1");
       // confirm custom editor dialog
       // close property sheet


There are some operators in Jelly providing functionality covering NetBeans wizards: WizardOperator, NewFileWizardOperator, NewJavaFileNameLocationStepOperator, NewProjectWizardOperator, NewJavaProjectNameLocationStepOperator, NewWebProjectNameLocationStepOperator, NewWebProjectSourcesStepOperator.

Example (from WizardsTest.java):

       // open new file wizard
       NewFileWizardOperator nfwo = NewFileWizardOperator.invoke();
       nfwo.selectFileType("Java Class");
       // go to next page
       // create operator for the next page
       NewJavaFileNameLocationStepOperator nfnlso = new NewJavaFileNameLocationStepOperator();
       // finish wizard

Using bundles

At the time there is not much focus on testing of localized NetBeans. So you can use hard coded string in your test cases and change them if labels in the IDE change. But in case you want to make your test cases locale independent and resistant to minor label changes, use resource bundles as described in this chapter.

Moving most of the functionality into operators makes tests live longer with no changes in the tests themselves, because most of the changes in tested code can be covered by operators changing. However, some of the functionality still could be uncovered.

One of the places where tests are tied to tested code version is string resources. Again, most of the resources will be used in operators. But the rest of them should be taken from NetBeans bundles, so even if a resource is changed for NetBeans, the tests use the right resource value anyway.

It can be done using the org.netbeans.jellytools.Bundle class. To know which bundle and key is used for a particular label, look at the sources or use [[JellyToolsFAQ#Q:_How_to_localize_test_cases.3F|other available methods].


       // "Confirm Object Deletion" dialog title
       String confirmTitle = Bundle.getString("org.openide.explorer.Bundle", "MSG_ConfirmDeleteObjectTitle");
       // "Help" main menu item
       String helpItem = Bundle.getStringTrimmed("org.netbeans.core.Bundle", "Menu/Help"); 

Using a Bundle class automatically makes I18N application testing possible, because localized resource values will be used instead.

Using Jemmy in tests

Classes provided by JellyTools have most methods necessary to perform operations in the "usual" way. So, if you do not need to do something "unusual", methods you need are probably already in JellyTools.

As was mentioned above JellyTools operators extend Jemmy operators, so you can use them as regular Jemmy operators. Additionally, most of the JellyTools operators have shortcuts to get operators for most of their sub components. These operators are, again, either Jemmy operators or JellyTools operators. So there is no need to create any operator yourself.

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo