Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

This tutorial describes how to use SWTBot to test Eclipse RCP applications. Within this tutorial Eclipse 4.6 is used.

1. User interface testing with SWTBot

SWTBot is an Eclipse project which supports testing the user interface of an SWT based application. SWTBot provides an API which allows you to interact with the user interface of the application. It supports validation of certain conditions on the user interface.

The Eclipse or SWT application is started and controlled by SWTBot.

If SWTBot is used to test Eclipse based applications, you need to run the JUnit test with a JUnit Plug-in Test run configuration. A JUnit plug-in test allows you to start and test Eclipse bundles.

2. Installation of SWTBot

Install SWTBot via the Eclipse Update manager (Help[Install New Software…​]). The update site for the SWTBot is: http://download.eclipse.org/technology/swtbot/releases/latest/

Install the SWTBot Eclipse Features and the SWTBot SWT Features.

3. SWTBot API

SWTBot is the base class for testing SWT applications.

The SWTWorkbenchBot class provides API to interact with Eclipse 3.x applications. The SWTWorkbenchBot class extends SWTBot. To test Eclipse 4.x RCP application you use the SWTBot class.

An user interface interaction may take some time, e.g., if the application reads some data. Therefore, SWTBot waits, by default, 5 seconds before throwing an exception. You can change the timeout via the following:

// Set the timeout to 6 seconds
SWTBotPreferences.TIMEOUT = 6000;

For details on the API usage please see SWTBot wiki.

NOTE: Testing an application with a login screen is currently not supported by SWTBot. See SWTBot FAQ.

3.1. Resetting the workbench in 3.x

JUnit does not require that the tests run in the same order as defined. To ensure that the Eclipse 3.x workbench is in the same state for each test you can use the following command.

bot.resetWorkbench();

3.2. Waiting for certain conditions

During UI tests, some actions may trigger long running operations. In this case, the test needs to wait until this operation finishes. Therefore the SWTBot class contains different overloaded methods like waitUntil, waitWhile and waitUntilWidgetAppears. All these methods expect an instance of the ICondition interface, where the condition for the wait operation is specified. The following snippet showns how such a condition can be defined for waitUntil and waitWhile.

@Test
public void testPerspectiveChange() {

    final String adminPerspectiveId = "com.example.adminperspective";
    // wait until admin perspective becomes active
    bot.waitUntil(new DefaultCondition() {

        @Override
        public boolean test() throws Exception {
            return adminPerspectiveId.equals(this.modelService.getActivePerspective(this.window));
        }

        @Override
        public String getFailureMessage() {
            return adminPerspectiveId + " has not become active in time";
        }
    });

    final String mainPerspectiveId = "com.example.mainperspective";
    // alternatively wait as long as the main perspective is still active
    bot.waitWhile(new DefaultCondition() {

        @Override
        public boolean test() throws Exception {
            return mainPerspectiveId.equals(this.modelService.getActivePerspective(this.window));
        }

        @Override
        public String getFailureMessage() {
            return mainPerspectiveId + " remains active for too long";
        }
    });

    // ... continue testing the perspectives contents
}

IConditions for the most use cases are predefined by the SWTBot framework. For 3.x application the org.eclipse.swtbot.eclipse.finder.waits.Conditions class and for E4 applications the org.eclipse.swtbot.e4.finder.waits.Conditions class can be used. Both classes are derived from org.eclipse.swtbot.swt.finder.waits.Conditions, which contains general SWT conditions.

@Test
public void testTableRowAmount() {

    SWTBotTable table = bot.table();
    int rowCount = 3;
    // choose a longer timeout than the default, because loading table contents takes longer
    int timeout = 10000;
    // check every second, if the condition is fulfilled
    int interval = 1000;
    bot.waitUntil(Conditions.tableHasRows(table, rowCount), timeout, interval);

    // ... continue working with the table rows
}

The Conditions classes also contain lots of generalized methods, which expect an org.hamcrest.Matcher instances in order to test a condition. General org.hamcrest.Matcher objects for those Conditions are:

swt bot matcher

An example for the WithText matcher is to wait for a Shell:

@Test
public void testShellOpened() {
    // open a shell with "Shell text" as text...

    // create a shellMatcher to wait for the previously opened shell
    Matcher<Shell> shellMatcher = WithText.withTextIgnoringCase("Shell text");
    // wait until the shell is opened
    bot.waitUntil(Conditions.waitForShell(shellMatcher));text
}

4. Possible pitfalls with SWTBot

This section contains possible pitfalls, which might come up when implementing SWTBot tests.

First of all define a org.eclipse.swt.widgets.Link to be tested in the UI code.

Link link = new Link(parent, SWT.NONE);
// add the <a> tags to visualize a underlined clickable blue hyperlink
link.setText("<a>www.vogella.com</a>");
link.addSelectionListener(new SelectionAdapter() {
    @Override
    public void widgetSelected(SelectionEvent e) {
        // ... open browser and go to vogella.com
    }
});

So the text applied to the Link is <a>www.vogella.com</a>, but in the UI you’ll see this:

vogella SWT Link

When this Link should now be accessed by the SWTBot using the text of this Link, <a>www.vogella.com</a> has to be used.

// even though only www.vogella.com is shown in the UI this won't work
SWTBotLink vogellaLink = bot.link("www.vogella.com");

// this is the valid way to access the Link
SWTBotLink vogellaLink = bot.link("<a>www.vogella.com</a>");

Another pitfall concerning a SWTBotLink is that invoking the click() might not work properly. Therefore the SWTBotLink also provides an overloaded version of the click() method with a String parameter, which contains the hyperlink text.

SWTBotLink vogellaLink = bot.link("<a>www.vogella.com</a>");
// explicitly specify where to click on
vogellaLink.click("www.vogella.com");

So the click(String hyperlinkText) method should always be used rather than just the simple click() method.

5. Prerequisites for this tutorial

This tutorial assumes that you have basic understanding of development for the Eclipse platform. Please see Eclipse RCP Tutorial or Eclipse Plug-in Tutorial if you need any basic information.

6. Exercise: Write SWTBot test

6.1. Install SWTBot

Ensure to install SWTBot into your Eclipse IDE. See Installation of SWTBot for detailed information.

6.2. Create project

Create a new plug-in called com.example.e4.rcp.todo.uitest and add the following dependencies to the MANIFEST.MF file:

  • org.eclipse.swt

  • org.junit

  • org.eclipse.swtbot.go

  • org.eclipse.swtbot.junit4_x

  • org.eclipse.swtbot.swt.finder

6.3. Create test

Write the following test class.

package com.example.e4.rcp.todo;

import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(SWTBotJunit4ClassRunner.class)
public class ExitHandlerTest {

    private static SWTBot bot;

    @BeforeClass
    public static void beforeClass() throws Exception {
        // don't use SWTWorkbenchBot here which relies on Platform 3.x
        bot = new SWTBot();
    }

    @Test
    public void executeExit() {
        // testing on hard-coded String just to have
        // a simple example


        bot.button("Login").click();

        SWTBotMenu fileMenu = bot.menu("File");
        Assert.assertNotNull(fileMenu);
        SWTBotMenu exitMenu = fileMenu.menu("Another Exit");
        Assert.assertNotNull(exitMenu);
        exitMenu.click();
    }

    @AfterClass
    public static void sleep() {
        bot.sleep(2000);
    }
}

6.4. Adjust launch configuration

Right-click on your test class and select Run ▸ JUnit Plug-in Test.

This test run should fail or result in error messages but it creates a launch configuration which you can adjust.

Select Run ▸ Run Configurations…​ and switch to the Main tab.

Select that your product should be started similar to the following screenshot.

Select the product which should be started

6.5. Validating

Run your test and verify that the test runs successfully. If you have used different text in your menu, adjust the test until it runs successfully.

7. Tutorial: Test Eclipse 3.x RCP applications

7.1. Create project

Create a new Eclipse RCP application called de.vogella.swtbot.app based on the Eclipse application with a view template.

Change the View class to the following.

package de.vogella.swtbot.app;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
    public void createPartControl(Composite parent) {
        Label label = new Label(parent, SWT.NONE);
        label.setText("My Label");
        Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
        text.setText("This is my text");

        // Define another text field but also assign an ID to this field for
        // SWTBot
        text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
        text.setText("This text has an ID");
        text.setData("org.eclipse.swtbot.widget.key", "text1");

    }

    /**
     * Passing the focus request to the viewer's control.
     */
    public void setFocus() {
    }
}

This view defines two text fields, one of them will be identified by SWTBot via the label and the other through an SWTBot specific ID.

7.2. Create test plug-in

Create another Eclipse plug-in called de.vogella.swtbot.tests.

Add the following dependencies to the MANIFEST.MF file for your test project.

  • org.eclipse.ui

  • org.junit4

  • org.hamcrest

  • org.eclipse.swtbot.swt.finder

  • org.eclipse.swtbot.eclipse.finder

Create the following class which defines the JUnit test.

package de.vogella.swtbot.tests;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class UserInterfaceTester {
    @Test
    public void test() {
        assertTrue(true);
    }

}

Right-click on the test and select menu:Run As [SWTBot Test]. In the launch configuration select your application and add the de.vogella.swtbot.tests and de.vogella.swtbot.app plugins and their dependencies to the launch configuration.

swtbot10

If everything runs correctly, you should get a green test. Change your test() method to the following to do some real testing.

package de.vogella.swtbot.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
import org.junit.Test;

public class UserInterfaceTester {
    private final SWTWorkbenchBot bot = new SWTWorkbenchBot();

    @Test
    public void test() {
        // find the text after the label "My Label"
        SWTBotText textWithLabel = bot.textWithLabel("My Label");
        // Set the focus and write a text into the text field
        textWithLabel.setFocus();
        assertEquals(textWithLabel.getText(), "This is my text");
        textWithLabel.selectAll();
        textWithLabel.typeText("Java rules them all");
        assertEquals(textWithLabel.getText(), "Java rules them all");

        // find the text with with the assigned id
        SWTBotText textWithId = bot.textWithId("text1");
        assertEquals(textWithId.getText(), "This text has an ID");

        // now lets find a view part
        SWTBotView viewById = bot.viewById("de.vogella.swtbot.app.view");
        assertNotNull(viewById);

        // Select the exit menu
        // bot.menu("/File").menu("Exit").click();

        assertTrue(true);
    }
}

Run your test again and verify that the test run successfully.

Change, for example, the content of one text field, re-run the test and verify that the test fails.

8. Screenshot

SWTBot can automatically generate screenshots of the running application if a test fails. To use this feature include the plug-in org.eclipse.swtbot.junit4_x into the dependencies of your test project. Annotate your class test with @RunWith(SWTBotJunit4ClassRunner.class). This generates screenshots in the screenshots folder or your test projects. If you do not see this folder in your project, try refreshing the project (F5).

You can trigger a screenshot in your code via the method bot.captureScreenshot(fileName).

9. Learn more about Eclipse 4 RCP development

I hope you enjoyed this tutorial. You find this tutorial and much more information also in the Eclipse 4 RCP book.

10. About this website

11. SWTBot Resources

11.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2017 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.