Automated Tests for Java Swing Guis

Automated tests for Java Swing GUIs

Recently I came across FEST which seemed promising, except that the developer announced in 2012 that development would not continue.

AssertJ is a fork of FEST that is working very well for me. It is actively maintained (at time of writing), supports Java 8, has assertions for a few popular libraries such as Guava and Joda Time, and is very well documented. It is also free and open.

How to get started: testing Java Swing GUI with AssertJ Swing

TL;DR: the example project can be found on GitHub.


Assuming this is a maven project, you'll firstly need to add at least two dependencies:

  1. A unit test framework (e.g. here junit – but could also use testng)
  2. The matching AssertJ Swing library (e.g. here assertj-swing-junit)

It could look like this (in your pom.xml:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-swing-junit</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>

Secondly, I usually go for one base test class to separate most of the test setup from the actual tests:

/**
* Base class for all my UI tests taking care of the basic setup.
*/
public class AbstractUiTest extends AssertJSwingTestCaseTemplate {

/**
* The main entry point for any tests: the wrapped MainWindow.
*/
protected FrameFixture frame;

/**
* Installs a {@link FailOnThreadViolationRepaintManager} to catch violations of Swing threading rules.
*/
@BeforeClass
public static final void setUpOnce() {
// avoid UI test execution in a headless environment (e.g. when building in CI environment like Jenkins or TravisCI)
Assume.assumeFalse("Automated UI Test cannot be executed in headless environment", GraphicsEnvironment.isHeadless());
FailOnThreadViolationRepaintManager.install();
}

/**
* Sets up this test's fixture, starting from creation of a new <code>{@link Robot}</code>.
*
* @see #setUpRobot()
* @see #onSetUp()
*/
@Before
public final void setUp() {
// call provided AssertJSwingTestCaseTemplate.setUpRobot()
this.setUpRobot();
// initialize the graphical user interface
MainWindow mainWindow = GuiActionRunner.execute(new GuiQuery<MainWindow>() {

@Override
protected MainWindow executeInEDT() throws Exception {
return MainApp.showWindow();
}
});
this.frame = new FrameFixture(this.robot(), mainWindow);
this.frame.show();
this.frame.resizeTo(new Dimension(600, 600));
onSetUp();
}

/**
* Subclasses that need to set up their own test fixtures in this method. Called as <strong>last action</strong> during {@link #setUp()}.
*/
protected void onSetUp() {
// default: everything is already set up
}

/*****************************************************************************************
* Here you could insert further helper methods, e.g. frequently used component matchers *
*****************************************************************************************/

/**
* Cleans up any resources used in this test. After calling <code>{@link #onTearDown()}</code>, this method cleans up resources used by this
* test's <code>{@link Robot}</code>.
*
* @see #cleanUp()
* @see #onTearDown()
*/
@After
public final void tearDown() {
try {
onTearDown();
this.frame = null;
} finally {
cleanUp();
}
}

/**
* Subclasses that need to clean up resources can do so in this method. Called as <strong>first action</strong> during {@link #tearDown()}.
*/
protected void onTearDown() {
// default: nothing more to tear down
}
}

The actual test class could look like this then:

public class MainWindowTest extends AbstractUiTest {

private JButtonFixture northButtonFixture;
private JButtonFixture southButtonFixture;

@Override
protected void onSetUp() {
this.northButtonFixture = this.frame.button(JButtonMatcher.withText("North"));
this.southButtonFixture = this.frame.button(JButtonMatcher.withText("South"));
}

@Test
public void testWithDifferingComponentMatchers() {
// use JTextComponentMatcher.any() as there is only one text input
this.frame.textBox(JTextComponentMatcher.any()).requireVisible().requireEnabled().requireNotEditable().requireEmpty();
this.northButtonFixture.requireVisible().requireEnabled().click();
// use value assigned in MainWindow class via JTextArea.setName("Center-Area") to identify component here
this.frame.textBox("Center-Area").requireText("North, ");

this.southButtonFixture.requireVisible().requireEnabled().click();
// write our own matcher
JTextComponentFixture centerArea = this.frame.textBox(new GenericTypeMatcher(JTextArea.class, true) {
@Override
protected boolean isMatching(Component component) {
return true;
}
});
centerArea.requireVisible().requireEnabled().requireText("North, South, ");
}

@Override
protected void onTearDown() {
this.northButtonFixture = null;
this.southButtonFixture = null;
}
}

Once you have such a basic setup in your project, you might want to look into the various kinds of component matcher there are and potentially introduce a couple setName() calls on various of your components you want to test, in order to make your life a bit easier.

Automated GUI Testing

I recommend the following open source tools (we are using them on our Java Swing applications):

  • UISpec4J - Non visual testing tool, very good for unit testing/TDD for the GUI application
  • Abbot - Is good for functional testing. Also have record & playback

You can use both or either one of them

From the commercial tools in my opinion the best is IBM Rational Functional Tester - it supports Java applications very well. However it is expensive and is focused on the record & replay approach which is not very reliable.

What is the best testing tool for Swing-based applications?

On our side, we use to test SWING GUI with FEST. This is an adapter on the classical swing robot, but it ease dramatically its use.

Combined with TestNG, We found it an easy way to simulate "human" actions trough the GUI.

What is a good automated test tool to test UI of Java Swing based windows application

Fest has a module for functional Swing testing, and it's actively maintained.

Java Swing UI test driver replacement for Fest

AssertJ Swing is a fork from FEST and seems to be currently updated.
Jubula from Eclipse and Marathon are other open source options.

MarathonITE adds bells and whistles to Marathon, comes with support and a proprietary license .

I am aware that this is an old question, but since it comes up when I search for Java Swing functional test automation, I hope this is useful for someone else.

JUnit Tests for GUI in Java

Java SE comes with a standard tool for doing just this, the Robot class. I've only ever used it to write bots for games and to remotely control a separate computer via a socket server/client pair, but it was actually intended to automate testing, and so it should work for you. The basic format is simple:

Robot bot = new Robot();
bot.mouseMove(10,10);
bot.mousePress(InputEvent.BUTTON1_MASK);
//add time between press and release or the input event system may
//not think it is a click
try{Thread.sleep(250);}catch(InterruptedException e){}
bot.mouseRelease(InputEvent.BUTTON1_MASK);

Of course you can simulate keyboard events in a similiar way as well using the appropriate keyPress/keyRelease methods. I've sometimes found it useful to use the screenCapture method of the robot class as well to seach for images on the screen and determine where to click.

Note: this does not require that the windows you are testing are built on awt/swing, however it does require that the java implementaton you are using supports awt.

Test an application GUI coded with Java Swing : best approach?

I've done what you've explained in the comment to the other answer.

Robot can be useful for various parts of the process but, depending on how it was written, the desire to follow best testing practices, and overall needs it can get limited quick. If you didn't write it or best coding practices keep you from getting access to or directly testing aspects of the application then other means are necessary.

My experience led me to tunnel down the main entry point using reflection to test the actual state (like text values of various components). Robot was only useful for my case to perform key events.

Ultimately, the answer(s) depend on many factors:

  1. Robot? - Sure, use it as far as it suits your needs.
  2. Do what's easiest while still meeting the requirements. If a screen shot will do, do it (with Robot). If you need more information you can get the components of a JFrame or JPanel and save what ever properties offered.
  3. This can be done a number of ways though investigation of the UI. Finding the button and doing doClick directly on it, moving the mouse with Robot and doing a mouse press, etc.
  4. When you instantiate a new Robot it will be linked to the main device. Nothing more is needed in simple scenarios than new Robot().keyPress(KeyEvent.VK_ENTER);

Given all that, there are pitfalls like focus. It's best to start your simulation/test and not touch any peripheral of the machine. Also, depending on the running time of some methods you may want to Thread.sleep() (as we regrettably did) or use joined threads.



Related Topics



Leave a reply



Submit