This tutorial describes how to use SWTBot to perform user interface testing for Eclipse applications and IDE plug-ins.

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.

SWTBot is the base class for testing SWT applications.

The SWTWorkbenchBot class provides API to interact with the Eclipse IDE and with 3.x RCP applications. The SWTWorkbenchBot class extends SWTBot.

To test Eclipse 4.x RCP application you use the SWTBot class.

2. Installation of SWTBot

2.1. IDE

Install SWTBot via the Eclipse Help  Install New Software…​ menu entry. Enter the https://download.eclipse.org/technology/swtbot/releases/latest/ URL into the Work with: field and install everything or the following selected features:

  • SWTBot for Eclipse Testing

  • SWTBot for SWT Testing

  • SWTBot JUnit5 Support

2.2. Command line build

Add the following to your target platform to me SWTBot available during your command line run:

        <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
            <repository location="https://download.eclipse.org/technology/swtbot/releases/latest/"/>
            <unit id="org.eclipse.swtbot.eclipse.feature.group" version="0.0.0"/>
            <unit id="org.eclipse.swtbot.e4.finder" version="0.0.0"/>
            <unit id="org.eclipse.swtbot.eclipse.test.junit.feature.group" version="0.0.0"/>
        </location>

3. 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.

4. Exercise: Write a SWTBot test for a generated RCP application

In this exercise, you develop an SWTBot test using JUnit5 for an RCP application created with the wizard.

This exercise assumes that you have installed SWTBot into your Eclipse IDE.

4.1. Create a new E4 application

If you have already created a RCP application named com.example.e4.rcp with the Eclipse wizard it is fine to reuse it.

Otherwise, create a new plug-in project named com.example.e4.rcp using the Eclipse RCP application template. Ensure you select the Create example content on the last tab.

swtbot testing10
swtbot testing20
swtbot testing30

4.2. Create project

Create a new plug-in called com.example.e4.swtbottests. Select No for the question if you want to create an rich client application.

Afterwards add the following dependencies to the MANIFEST.MF file:

  • org.eclipse.swt

  • org.junit.jupiter.api

  • org.eclipse.swtbot.go

  • org.eclipse.swtbot.swt.e4.finder

4.3. Create test

Write the following test class.

package com.example.e4.swtbottests;

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

import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class ExitHandlerTest {

    private static SWTBot bot;

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

    @Test
    public void executeExit() {
        SWTBotMenu fileMenu = bot.menu("File");
        assertNotNull(fileMenu);
        SWTBotMenu exitMenu = fileMenu.menu("Quit");
        assertNotNull(exitMenu);
        exitMenu.click();

        SWTBotShell shell = bot.shell("Confirmation");
        SWTBot childBot = new SWTBot(shell.widget);
        SWTBotButton button = childBot.button("Cancel");
        assertTrue(button.isEnabled());
        button.click();
    }



//  @AfterEach
//  public void sleep() {
//      bot.sleep(2000);
//  }
}

4.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…​.

Configure SWTBot to run outside the UI thread.

Select the product which should be started

Switch to the Main tab.

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

Select the product which should be started

4.5. Validate

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.

4.6. Create another test

Create another test and run it.

package com.vogella.tasks.ui;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class CheckWidgetsInView {

    private static SWTBot bot;

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

    @Test
    public void findView() {
        SWTBotText textWithMessage = bot.textWithMessage("Enter text to mark part as dirty");
        assertNotNull(textWithMessage);
        assertTrue(textWithMessage.isEnabled());
    }

    @Test
    public void findTable() {
        SWTBotTable table = bot.table();
        assertNotNull(table);
        assertEquals(5, table.rowCount(), "Table should have 5 entries");
    }
}

5. Tutorial: Test Eclipse 3.x RCP applications

5.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.

5.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.

6. More on SWTBot

6.1. Timeout

A 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.

6.2. 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();

6.3. 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
}

7. 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.

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 and get support

This tutorial continues on Eclipse RCP online training or Eclipse IDE extensions with lots of video material, additional exercises and much more content.

10. SWTBot Resources