# SWTBot SWTBot is an open-source Java-based functional testing tool for testing SWT (Standard Widget Toolkit) and Eclipse-based applications. It provides a high-level API that interacts with SWT widgets using operations that mirror user interactions, making it easy to transform user scenarios into automated UI tests. SWTBot hides the complexities of SWT threading and widget lookup, offering simple and readable APIs suitable for everyone involved in functional testing. The framework supports testing plain SWT applications, Eclipse plugins, RCP applications, and GEF/GMF diagram editors. SWTBot includes features like test recording and code generation, headless test execution for CI/CD environments, JUnit 4 and JUnit 5 integration, and screenshot capture on test failures. It runs on all platforms that SWT supports and integrates seamlessly with Maven/Tycho builds and CI tools like Jenkins and Travis. ## SWTBot - Basic Widget Interaction The `SWTBot` class is the main entry point for interacting with SWT widgets. It provides convenience methods to find and interact with buttons, text fields, menus, trees, tables, and other SWT controls using labels, mnemonics, tooltips, or widget indexes. ```java import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; import org.eclipse.swtbot.swt.finder.widgets.SWTBotCombo; import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox; public class BasicWidgetExample { private SWTBot bot = new SWTBot(); public void interactWithWidgets() { // Find and click a button by its text bot.button("Submit").click(); // Find a button by label (adjacent Label widget) bot.buttonWithLabel("User Action").click(); // Find a button in a specific group bot.buttonInGroup("Edit", "Bank Account").click(); // Work with text fields SWTBotText nameField = bot.textWithLabel("Name:"); nameField.setText("John Doe"); String value = nameField.getText(); // Work with combo boxes SWTBotCombo countryCombo = bot.comboBoxWithLabel("Country:"); countryCombo.setSelection("United States"); countryCombo.setText("Canada"); // for editable combos // Work with checkboxes SWTBotCheckBox checkbox = bot.checkBox("Remember me"); checkbox.select(); // check checkbox.deselect(); // uncheck checkbox.click(); // toggle // Work with radio buttons bot.radio("Option A").click(); // Find widgets by tooltip bot.buttonWithTooltip("Save changes").click(); // Find widgets by index when multiple exist bot.button("OK", 1).click(); // second OK button (0-indexed) } } ``` ## SWTWorkbenchBot - Eclipse Workbench Testing `SWTWorkbenchBot` extends `SWTBot` with methods specific to Eclipse workbench testing, including views, editors, perspectives, and Eclipse-specific menus. Use this class when testing Eclipse plugins or RCP applications. ```java import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor; import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(SWTBotJunit4ClassRunner.class) public class EclipseWorkbenchTest { private static SWTWorkbenchBot bot; @BeforeClass public static void setup() { bot = new SWTWorkbenchBot(); // Close Welcome view if present try { bot.viewByTitle("Welcome").close(); } catch (Exception e) { // Welcome view not found, continue } } @Test public void testViewOperations() { // Open a view using menu bot.menu("Window").menu("Show View").menu("Other...").click(); bot.shell("Show View").activate(); bot.tree().expandNode("General").select("Console"); bot.button("Open").click(); // Find and interact with views SWTBotView consoleView = bot.viewByTitle("Console"); consoleView.show(); // bring to front consoleView.maximize(); // maximize consoleView.restore(); // restore from maximized consoleView.close(); // close the view // Access view's toolbar buttons SWTBotView view = bot.viewByTitle("Package Explorer"); view.toolbarButton("Collapse All").click(); // Access view menu view.viewMenu().menu("Filters...").click(); } @Test public void testEditorOperations() { // Create a new file to get an editor bot.menu("File").menu("New").menu("File").click(); bot.textWithLabel("File name:").setText("test.txt"); bot.button("Finish").click(); // Work with the active editor SWTBotEditor editor = bot.activeEditor(); editor.toTextEditor().setText("Hello World"); editor.save(); editor.close(); // Find editor by title SWTBotEditor namedEditor = bot.editorByTitle("MyFile.java"); namedEditor.show(); } @Test public void testPerspectiveSwitch() { // Switch perspective via menu bot.menu("Window").menu("Open Perspective").menu("Other...").click(); bot.shell("Open Perspective").activate(); bot.table().select("Debug"); bot.button("Open").click(); // Or directly reset perspective bot.resetPerspective(); } } ``` ## Menu Navigation SWTBot provides fluent API for navigating and clicking menus, including context menus on widgets. Menus can be accessed by text, mnemonic, or index. ```java import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; public class MenuNavigationExample { private SWTBot bot = new SWTBot(); public void navigateMenus() { // Navigate nested menus using chained menu() calls bot.menu("File").menu("New").menu("Project...").click(); // Access menu by mnemonic (Alt+F for &File) bot.menu("File").click(); // Check if menu is enabled/checked SWTBotMenu editMenu = bot.menu("Edit"); boolean enabled = editMenu.isEnabled(); SWTBotMenu autoSave = bot.menu("File").menu("Auto Save"); boolean checked = autoSave.isChecked(); // Context menu on a tree item SWTBotTree tree = bot.tree(); tree.getTreeItem("Project").contextMenu("Refresh").click(); // Context menu on a table row SWTBotTable table = bot.table(); table.getTableItem("Item 1").contextMenu("Delete").click(); // Navigate context menu hierarchy tree.getTreeItem("src").contextMenu("New").menu("Class").click(); } } ``` ## Tree Widget Operations SWTBot provides comprehensive support for tree widgets, including expanding/collapsing nodes, selecting items, and handling lazy-loaded trees. ```java import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; import org.eclipse.swtbot.swt.finder.waits.DefaultCondition; public class TreeOperationsExample { private SWTBot bot = new SWTBot(); public void workWithTrees() { SWTBotTree tree = bot.tree(); // Expand a single node SWTBotTreeItem projectNode = tree.expandNode("MyProject"); // Chain expand multiple levels SWTBotTreeItem classNode = tree .expandNode("MyProject") .expandNode("src") .expandNode("com.example") .select("MyClass.java"); // Double-click to open classNode.doubleClick(); // Get all items at root level SWTBotTreeItem[] rootItems = tree.getAllItems(); // Get children of a node SWTBotTreeItem[] children = projectNode.getItems(); // Select multiple items tree.select("Item1", "Item2", "Item3"); // Check/uncheck checkable tree items SWTBotTreeItem checkableItem = tree.getTreeItem("Enable Feature"); checkableItem.check(); checkableItem.uncheck(); // Handle lazy-loaded trees waitForTreeItemChildren(projectNode); } // Helper for lazy-loaded trees that populate on expand private void waitForTreeItemChildren(final SWTBotTreeItem item) { bot.waitUntil(new DefaultCondition() { @Override public boolean test() throws Exception { if (item.isExpanded()) { item.collapse(); } item.expand(); return item.getItems().length > 0; } @Override public String getFailureMessage() { return "Tree item did not populate children"; } }); } } ``` ## Table Widget Operations SWTBot provides methods to interact with SWT Table widgets, including selecting rows, reading cell values, and working with checkable tables. ```java import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTableItem; public class TableOperationsExample { private SWTBot bot = new SWTBot(); public void workWithTables() { SWTBotTable table = bot.table(); // Get table dimensions int rowCount = table.rowCount(); int columnCount = table.columnCount(); // Select row by index table.select(0); // Select row by text in first column table.select("MyItem"); // Select multiple rows table.select(0, 2, 4); // Get a specific table item SWTBotTableItem item = table.getTableItem("MyItem"); SWTBotTableItem itemByIndex = table.getTableItem(0); // Read cell value (column index) String cellValue = item.getText(1); // second column // Double-click to open/edit item.doubleClick(); // Work with checkable tables SWTBotTableItem checkableRow = table.getTableItem("Feature X"); checkableRow.check(); boolean isChecked = checkableRow.isChecked(); checkableRow.uncheck(); // Click on specific cell item.click(2); // click third column // Context menu on table item item.contextMenu("Properties").click(); // Iterate all rows for (int i = 0; i < table.rowCount(); i++) { SWTBotTableItem row = table.getTableItem(i); System.out.println(row.getText()); } } } ``` ## Shell and Dialog Handling SWTBot provides methods to find, activate, and interact with shells (windows/dialogs). This is essential for handling modal dialogs and multiple windows. ```java import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.waits.Conditions; public class ShellHandlingExample { private SWTBot bot = new SWTBot(); public void workWithShells() { // Get the currently active shell SWTBotShell activeShell = bot.activeShell(); // Find shell by title SWTBotShell dialog = bot.shell("Preferences"); // Activate a shell (bring to front and focus) dialog.activate(); // Wait for a shell to appear bot.waitUntil(Conditions.shellIsActive("Save Resource")); // Work with the dialog using its bot SWTBotShell prefsDialog = bot.shell("Preferences"); prefsDialog.activate(); SWTBot dialogBot = prefsDialog.bot(); dialogBot.tree().select("General"); dialogBot.button("Apply").click(); dialogBot.button("OK").click(); // Close a shell SWTBotShell warningDialog = bot.shell("Warning"); warningDialog.close(); // Get all open shells SWTBotShell[] shells = bot.shells(); for (SWTBotShell shell : shells) { System.out.println("Open shell: " + shell.getText()); } // Check if shell is active/visible boolean isActive = dialog.isActive(); boolean isOpen = dialog.isOpen(); } public void handleConfirmationDialog() { // Trigger action that opens dialog bot.button("Delete").click(); // Handle confirmation dialog SWTBotShell confirmDialog = bot.shell("Confirm Delete"); confirmDialog.activate(); confirmDialog.bot().button("Yes").click(); } } ``` ## Wait Conditions and Synchronization SWTBot provides a powerful waiting mechanism to synchronize test execution with asynchronous UI operations. Use `waitUntil` and `waitWhile` with built-in or custom conditions. ```java import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.waits.Conditions; import org.eclipse.swtbot.swt.finder.waits.DefaultCondition; import org.eclipse.swtbot.swt.finder.waits.ICondition; import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; public class WaitConditionsExample { private SWTBot bot = new SWTBot(); public void useBuiltInConditions() { // Wait for a shell to appear bot.waitUntil(Conditions.shellIsActive("Progress")); // Wait for a shell to close SWTBotShell progressShell = bot.shell("Progress"); bot.waitUntil(Conditions.shellCloses(progressShell)); // Wait for widget to be enabled bot.waitUntil(Conditions.widgetIsEnabled(bot.button("Next"))); // Wait for table to have rows SWTBotTable table = bot.table(); bot.waitUntil(Conditions.tableHasRows(table, 5)); // Wait with custom timeout (10 seconds) bot.waitUntil(Conditions.shellIsActive("Long Operation"), 10000); // Wait with custom timeout and poll interval bot.waitUntil(Conditions.shellIsActive("Dialog"), 10000, 500); } public void useCustomCondition() { // Create custom condition ICondition tablePopulated = new DefaultCondition() { @Override public boolean test() throws Exception { return bot.table().rowCount() > 0; } @Override public String getFailureMessage() { return "Table was not populated within timeout"; } }; bot.waitUntil(tablePopulated, 15000); } public void waitWhileExample() { // Wait while a condition is true (opposite of waitUntil) // Useful for waiting for progress dialogs to disappear ICondition progressVisible = new DefaultCondition() { @Override public boolean test() throws Exception { try { bot.shell("Loading..."); return true; // still loading } catch (Exception e) { return false; // loading dialog gone } } @Override public String getFailureMessage() { return "Progress dialog did not close"; } }; bot.waitWhile(progressVisible, 30000); } } ``` ## SWTBotPreferences - Configuration Settings `SWTBotPreferences` allows you to configure timeout values, playback speed, screenshot settings, and keyboard layout. These can be set programmatically or via system properties. ```java import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; public class ConfigurationExample { public void configureTimeouts() { // Set widget lookup timeout (default: 5000ms) SWTBotPreferences.TIMEOUT = 10000; // 10 seconds // Set playback delay between actions (default: 0ms) // Useful for debugging or demonstrations SWTBotPreferences.PLAYBACK_DELAY = 100; // 100ms between actions // Set poll interval for wait conditions (default: 500ms) // Note: DEFAULT_POLL_DELAY is final, set via system property // -Dorg.eclipse.swtbot.playback.poll.delay=250 } public void configureScreenshots() { // Directory for failure screenshots SWTBotPreferences.SCREENSHOTS_DIR = "target/screenshots"; // Screenshot format (BMP, GIF, ICO, JPEG, JPG, PNG, TIFF) SWTBotPreferences.SCREENSHOT_FORMAT = "png"; // Maximum number of screenshots to keep SWTBotPreferences.MAX_ERROR_SCREENSHOT_COUNT = 50; } public void configureKeyboard() { // Set keyboard layout for typing SWTBotPreferences.KEYBOARD_LAYOUT = "EN_US"; // Set interval between keystrokes (default: 50ms) SWTBotPreferences.TYPE_INTERVAL = 30; // Set keyboard strategy SWTBotPreferences.KEYBOARD_STRATEGY = "org.eclipse.swtbot.swt.finder.keyboard.SWTKeyboardStrategy"; } } // System properties equivalent (set in launch configuration or pom.xml): // -Dorg.eclipse.swtbot.search.timeout=10000 // -Dorg.eclipse.swtbot.playback.delay=100 // -Dorg.eclipse.swtbot.screenshots.dir=target/screenshots // -Dorg.eclipse.swtbot.screenshot.format=png // -Dorg.eclipse.swtbot.keyboard.layout=EN_US ``` ## JUnit 4 Test Structure SWTBot provides JUnit 4 integration with a custom test runner that ensures proper thread handling. Use `@RunWith(SWTBotJunit4ClassRunner.class)` for automatic screenshot capture on failure. ```java import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; @RunWith(SWTBotJunit4ClassRunner.class) public class CreateJavaProjectTest { private static SWTWorkbenchBot bot; @BeforeClass public static void beforeClass() throws Exception { bot = new SWTWorkbenchBot(); // Close welcome view try { bot.viewByTitle("Welcome").close(); } catch (Exception e) { // ignore } } @Before public void setUp() throws Exception { // Setup before each test } @Test public void canCreateANewJavaProject() throws Exception { // Open New Project wizard bot.menu("File").menu("New").menu("Project...").click(); SWTBotShell shell = bot.shell("New Project"); shell.activate(); // Select Java Project bot.tree().expandNode("Java").select("Java Project"); bot.button("Next >").click(); // Enter project name bot.textWithLabel("Project name:").setText("MyFirstProject"); // Finish wizard bot.button("Finish").click(); // Verify project was created SWTBotView packageExplorer = bot.viewByTitle("Package Explorer"); packageExplorer.show(); assertTrue(bot.tree().getTreeItem("MyFirstProject").isVisible()); } @After public void tearDown() throws Exception { // Cleanup after each test // Close any open dialogs SWTBotShell[] shells = bot.shells(); for (SWTBotShell shell : shells) { if (!shell.getText().contains("Eclipse")) { shell.close(); } } } @AfterClass public static void afterClass() { // Final cleanup bot.resetWorkbench(); } } ``` ## JUnit 5 Test Structure SWTBot 3.0.0+ supports JUnit 5. Use the `SWTBotJunit5Extension` for screenshot capture on failure. ```java import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.swt.finder.junit5.SWTBotJunit5Extension; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(SWTBotJunit5Extension.class) public class JUnit5ExampleTest { private static SWTWorkbenchBot bot; @BeforeAll public static void beforeAll() { bot = new SWTWorkbenchBot(); try { bot.viewByTitle("Welcome").close(); } catch (Exception e) { // ignore } } @BeforeEach public void beforeEach() { // Setup before each test } @Test public void testOpenPreferences() { bot.menu("Window").menu("Preferences").click(); var prefsShell = bot.shell("Preferences"); prefsShell.activate(); assertTrue(prefsShell.isOpen()); bot.button("Cancel").click(); } @AfterEach public void afterEach() { // Cleanup after each test } @AfterAll public static void afterAll() { // Final cleanup } } ``` ## GEF/GMF Diagram Editor Testing SWTBot provides special support for testing GEF (Graphical Editing Framework) and GMF (Graphical Modeling Framework) diagram editors through `SWTBotGefEditor`. ```java import org.eclipse.swtbot.eclipse.gef.finder.SWTBotGefTestCase; import org.eclipse.swtbot.eclipse.gef.finder.widgets.SWTBotGefEditPart; import org.eclipse.swtbot.eclipse.gef.finder.widgets.SWTBotGefEditor; public class GefDiagramTest extends SWTBotGefTestCase { private SWTBotGefEditor editor; @Override protected void setUp() throws Exception { super.setUp(); // Close welcome page try { bot.viewByTitle("Welcome").close(); } catch (Exception e) { // ignore } } public void testCreateDiagramElements() throws Exception { // Create or open a diagram file first // ... (project/file creation code) // Get the GEF editor editor = bot.gefEditor("mydiagram.diagram"); // Activate a tool from the palette editor.activateTool("Rectangle"); // Click to create an element at position editor.click(100, 100); // Create element by dragging (for tools that require drag) editor.activateTool("Circuit"); editor.drag(55, 55, 150, 100); // Create a connection between elements editor.activateTool("Connection"); editor.click(100, 100); // source editor.click(200, 200); // target // Find and select an edit part by label SWTBotGefEditPart editPart = editor.getEditPart("MyElement"); editPart.select(); editPart.click(); // Direct edit (rename) an element editPart.activateDirectEdit(); editor.directEditType("New Name"); // Drag an element to new position editor.drag(100, 100, 300, 300); // Access context menu on edit part editPart.click(); editor.clickContextMenu("Delete"); // Save the editor bot.menu("File").menu("Save").click(); } } ``` ## UI Thread Execution SWTBot runs tests on a non-UI thread, but some operations require UI thread access. Use `UIThreadRunnable` for such cases. ```java import org.eclipse.swt.widgets.Display; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; import org.eclipse.swtbot.swt.finder.results.VoidResult; import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.ui.PlatformUI; public class UIThreadExample { public void executeOnUIThread() { // Execute code that requires UI thread (sync) UIThreadRunnable.syncExec(new VoidResult() { @Override public void run() { // Code that needs UI thread PlatformUI.getWorkbench() .getActiveWorkbenchWindow() .getShell() .forceActive(); } }); // Execute and return a value from UI thread String shellTitle = UIThreadRunnable.syncExec(new Result() { @Override public String run() { return PlatformUI.getWorkbench() .getActiveWorkbenchWindow() .getShell() .getText(); } }); // Async execution (non-blocking) UIThreadRunnable.asyncExec(new VoidResult() { @Override public void run() { // Code that needs UI thread but doesn't need result } }); } // Alternative using Display directly public void usingDisplay() { Display.getDefault().syncExec(new Runnable() { @Override public void run() { // UI thread code } }); } } ``` ## Custom Widget Testing SWTBot can test custom SWT controls by creating wrapper classes that extend `AbstractSWTBot`. ```java import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; import org.eclipse.swtbot.swt.finder.results.VoidResult; import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot; import org.hamcrest.SelfDescribing; import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType; // Custom SWT widget class QCombo extends org.eclipse.swt.widgets.Composite { // ... custom implementation public void setSelectedItem(String item) { /* ... */ } public String getSelectedItem() { return null; } } // SWTBot wrapper for custom widget public class SWTBotQCombo extends AbstractSWTBot { public SWTBotQCombo(QCombo widget) throws WidgetNotFoundException { this(widget, null); } public SWTBotQCombo(QCombo widget, SelfDescribing description) throws WidgetNotFoundException { super(widget, description); } public void setSelection(final String item) { UIThreadRunnable.asyncExec(new VoidResult() { @Override public void run() { widget.setSelectedItem(item); } }); } public String getSelection() { return syncExec(() -> widget.getSelectedItem()); } } // Usage in tests class CustomWidgetTest { private SWTBot bot = new SWTBot(); public void testCustomWidget() { // Find custom widget QCombo widget = bot.widget(widgetOfType(QCombo.class)); // Wrap it SWTBotQCombo qCombo = new SWTBotQCombo(widget); // Use the wrapper qCombo.setSelection("Option 1"); String selected = qCombo.getSelection(); } } ``` ## Maven/Tycho Integration Configure SWTBot tests to run in Maven builds using the Tycho Surefire plugin. The key is setting `useUIHarness=true` and `useUIThread=false`. ```xml eclipse-test-plugin org.eclipse.tycho tycho-surefire-plugin ${tycho.version} true false org.eclipse.sdk.ide org.eclipse.ui.ide.workbench -Dorg.eclipse.swtbot.search.timeout=20000 -Dorg.eclipse.swtbot.playback.delay=50 :0 ``` ## Headless Test Execution Run SWTBot tests from command line or CI environments without a visible display. Requires proper X server configuration on Linux. ```bash # Linux: Start virtual display with Xvfb or Xvnc Xvfb :99 -screen 0 1024x768x24 & export DISPLAY=:99 # Or use Xephyr for visible testing in separate window Xephyr -screen 1024x768 :51 & export DISPLAY=:51 metacity --sm-disable --replace & # Run SWTBot tests via command line java \ -Xms256M -Xmx768M \ -jar /path/to/eclipse/plugins/org.eclipse.equinox.launcher_*.jar \ -application org.eclipse.swtbot.eclipse.junit.headless.swtbottestapplication \ -testApplication org.eclipse.ui.ide.workbench \ -data /path/to/workspace \ -testPluginName com.example.tests \ -className com.example.tests.AllTests \ formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,/path/to/results.xml \ formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter \ -os linux -ws gtk -arch x86_64 \ -consoleLog # Install SWTBot into target application via p2 java -jar plugins/org.eclipse.equinox.launcher_*.jar \ -application org.eclipse.equinox.p2.director \ -repository http://download.eclipse.org/technology/swtbot/releases/latest/ \ -installIU org.eclipse.swtbot.eclipse.test.junit.feature.group \ -consoleLog -noSplash ``` ## Test Recording and Code Generation SWTBot includes a recorder that monitors UI actions and generates test code automatically. Enable it by installing the generator plugin and setting a system property. ```java // Programmatically start the recorder from your application import org.eclipse.swtbot.generator.ui.StartupRecorder; public class RecorderExample { public void startRecorder() { // Open the basic recorder dialog StartupRecorder.openRecorder("org.eclipse.swtbot.generator.dialog.basic"); // Or the JDT-aware recorder StartupRecorder.openRecorder("org.eclipse.swtbot.generator.dialog.jdt"); } } // To enable recorder at startup, add to your eclipse.ini or launch config: // -Dorg.eclipse.swtbot.generator.enable=true // Or install via p2 and configure target platform: // java -jar plugins/org.eclipse.equinox.launcher_*.jar \ // -application org.eclipse.equinox.p2.director \ // -repository \ // -installIU org.eclipse.swtbot.generator // Generated code example (output from recorder): // bot.menu("File").menu("New").menu("Project...").click(); // bot.tree().expandNode("Java").select("Java Project"); // bot.button("Next >").click(); // bot.textWithLabel("Project name:").setText("TestProject"); // bot.button("Finish").click(); ``` ## Summary SWTBot is the de facto standard for automated UI testing of SWT, Eclipse plugins, and RCP applications. Its primary use cases include: automated regression testing to catch UI bugs early, continuous integration testing in Jenkins/Travis/GitHub Actions pipelines, acceptance testing to verify user scenarios work correctly, and automated smoke testing of Eclipse-based products. The framework excels at simulating real user interactions like clicking buttons, entering text, navigating menus, and manipulating trees and tables. Integration patterns typically involve creating test plugins that depend on SWTBot bundles, using `SWTWorkbenchBot` for Eclipse workbench testing or `SWTBot` for plain SWT applications, and running tests with the JUnit 4/5 runners. For CI/CD, tests are executed headlessly using Xvfb/Xvnc on Linux or the Tycho Surefire plugin for Maven builds. The wait conditions API is essential for handling asynchronous operations, and the preferences system allows fine-tuning timeouts and playback speeds. Custom widgets can be tested by creating wrapper classes, and GEF/GMF diagrams have dedicated support through `SWTBotGefEditor`. The test recorder accelerates test development by generating code from manual interactions.