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 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
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"/>
<unit id="org.eclipse.swtbot.e4.finder"/>
<unit id="org.eclipse.swtbot.eclipse.test.junit.feature.group"/>
</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: Create an RCP application using the Eclipse wizard
In the following exercise, you’ll create an Eclipse RCP application using a template and launch it via the IDE. The generated files are not yet explained, but this should enable you to see a running application and review the involved configuration files.
4.1. Create project
Create a project named com.example.e4.rcp
via the menu entry.

Use the settings similar to the following screenshots.

Press Next.

Press Next.

Press Next.
On the last wizard page, select the Create sample content (parts, menu etc.) flag. Via this flag you configure that the generated application has example content, e.g., a view and some menu and toolbar entries.

The wizard adds the |
4.2. Launch your application via the product file
Open the generated product file by double-clicking on the product file.

Switch to the Overview tab in the editor and press the Launch an Eclipse application hyperlink to start your application. This option is highlighted in the screenshot below.

4.3. Validate
As a result your Eclipse application should start. The application should look similar to the following screenshot.

4.4. Error analysis
If you see an empty window, it means you pressed the Finish button too early (after selecting the template) or forgot to select the Create sample content
flag on the last tab.
To fix that, delete the generated plug-in and perform the creation again, this time selecting the correct values in Exercise: Create an RCP application using the Eclipse wizard.
5. Exercise: Write a SWTBot test for a generated RCP application
In this exercise, you develop an SWTBot test using JUnit5 for the com.example.e4.rcp
RCP application.
This exercise assumes that you have installed SWTBot into your Eclipse IDE.
5.1. Create project
Create a new plug-in named com.example.e4.swtbot.tests. Select No for the question if you want to create an rich client application.
The .tests extension will let Maven Tycho detect the project as a test project. |
Afterwards add the following plug-in dependencies to the MANIFEST.MF file:
-
org.eclipse.swt
-
org.eclipse.swtbot.swt.finder
-
org.eclipse.jface
-
org.eclipse.swtbot.e4.finder
-
org.eclipse.swtbot.swt.finder
-
org.slf4j.api
-
com.example.e4.rcp
Add also the following package dependencies to the MANIFEST.MF file:
-
org.junit.jupiter.api
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Swtbottests
Bundle-SymbolicName: com.example.e4.swtbot.tests
Bundle-Version: 1.0.0.qualifier
Import-Package: org.junit.jupiter.api;version="5.12.2"
Bundle-Vendor: EXAMPLE
Require-Bundle: org.eclipse.swt,
org.eclipse.jface,
org.eclipse.swtbot.e4.finder;bundle-version="4.3.0",
org.eclipse.swtbot.swt.finder;bundle-version="4.3.0",
org.slf4j.api;bundle-version="1.7.30",
com.example.e4.rcp;bundle-version="1.0.0"
Automatic-Module-Name: com.example.e4.swtbottests
Bundle-RequiredExecutionEnvironment: JavaSE-21
5.2. 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);
// }
}
5.3. Adjust launch configuration
Right-click on your test class and select
.This test run should fail or result in error messages but it creates a launch configuration which you can adjust.
Select
.Configure SWTBot to run outside the UI thread.

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

5.4. Add build.properties
Add the following content to the build.properties file of your test project.
pom.model.property.tycho.surefire.useUIHarness = true
pom.model.property.tycho.surefire.useUIThread = true
5.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.
5.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");
}
}
6. Tutorial: Test Eclipse 3.x RCP applications
6.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.
6.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.

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 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.
7. More on SWTBot
7.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.
7.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();
7.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 to test a condition.
General org.hamcrest.Matcher
objects for those Conditions
are:

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
}
8. Possible pitfalls with SWTBot
This section contains possible pitfalls, which might come up when implementing SWTBot tests.
8.1. Accessing a Link and clicking on it
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:

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.
9. 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)
.
10. 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.
11. SWTBot Resources
11.1. vogella Java example code
If you need more assistance we offer Online Training and Onsite training as well as consulting