Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Linux Tools Project/SWTBot Workarounds"

m
(Radio Button Selection Problems)
 
(3 intermediate revisions by 2 users not shown)
Line 5: Line 5:
 
Support for SWTBot itself is available [https://wiki.eclipse.org/SWTBot/Support here].
 
Support for SWTBot itself is available [https://wiki.eclipse.org/SWTBot/Support here].
  
= Tree Item Expansion Failure =
+
= Main Menu Items Not Found =
  
 
== Description ==
 
== Description ==
Sometimes expanding a SWTBotTree (or SWTBotTreeItem) with the expandNode method will have no effect, causing tests that rely on (initially hidden) tree nodes to fail or throw errors. Note that this problem can happen in tests even if previous runs have succeeded and no changes to the code have been made since.
 
  
This problem is not due to concurrency or race conditions, so sleeping or using a wait condition to wait for a node to appear will not work. It is also unlikely to happen during local test runs, making it difficult to debug.
+
When trying to access a menu item from the main Eclipse shell with ''bot.menu(String)'', a WidgetNotFound exception may be thrown. An example case of this is accessing the File menu with ''bot.menu("File")''. The reason this exception occurs is because the main shell must be active whenever a menu item is accessed; otherwise, the menu widget will not be seen by the bot.
  
 
== Symptoms ==
 
== Symptoms ==
  
* Tests that haven't been modified & were successful in previous builds are failing or throwing errors in later builds, with messages like "assertation failed:" or "could not find node with text: <name>"
+
* Menus can be clicked at certain points in the test, but not others
* The failed tests succeed when run locally, or when the offending build is retriggered or rebased, but fail again sometime later
+
* A menu is clicked on to open a dialog shell, but after that shell is closed, another attempt to access a menu item fails
 +
 
 +
A likely cause of these symptoms is the loss of focus of the main shell after certain operations, especially the appearance of new shells.
  
 
== Workaround ==
 
== Workaround ==
  
If the Shell containing the desired parent tree supports a text search, you should use that to search for the nodes you want to reveal & select rather than expanding nodes directly.
+
As the main Eclipse shell must be active before a menu item is accessed, the main shell should be captured and stored in a field variable so that it can be brought into focus at any time. Call the following method at the beginning of a test class (preferably at the start of a @BeforeClass method) to safely capture the shell:
 
+
For instance, if you want to create use SWTBot to create a C Project with the "New Project" wizard, you should get SWTBot to type "C Project" in the wizard's search bar (shell.bot().text()), which will reliably expand the "C/C++" node and reveal its child "C Project" node.
+
 
+
As expanding nodes with this method happens asynchronously relative to SWTBot, you will need a wait condition to halt execution until the node is ready. Below is a DefaultCondition extension that performs this task.
+
  
 
<pre>
 
<pre>
private static class NodeAvailableAndSelect extends DefaultCondition {
+
public static void getMainShell() {
 +
    SWTWorkbenchBot bot = new SWTWorkbenchBot();
 +
    mainShell = null;  // statically defined elsewhere
  
private SWTBotTree tree;
+
    for (int i = 0, attempts = 100; i < attempts; i++) {
private String parent;
+
        for (SWTBotShell shell : bot.shells()) {
private String node;
+
            if (shell.getText().contains("Eclipse Platform")) {
 
+
                mainShell = shell;
/**
+
                shell.setFocus();
* Wait for a tree node (with a known parent) to become visible, and select it
+
                break;
* when it does. Note that this wait condition should only be used after having
+
            }
* made an attempt to reveal the node.
+
        }
* @param tree The SWTBotTree that contains the node to select.
+
    }
* @param parent The text of the parent node that contains the node to select.
+
* @param node The text of the node to select.
+
*/
+
NodeAvailableAndSelect(SWTBotTree tree, String parent, String node){
+
this.tree = tree;
+
this.node = node;
+
this.parent = parent;
+
}
+
 
+
@Override
+
public boolean test() {
+
try {
+
SWTBotTreeItem parentNode = tree.getTreeItem(parent);
+
parentNode.getNode(node).select();
+
return true;
+
} catch (WidgetNotFoundException e) {
+
return false;
+
}
+
}
+
 
+
@Override
+
public String getFailureMessage() {
+
return "Timed out waiting for " + node; //$NON-NLS-1$
+
}
+
 
}
 
}
 
</pre>
 
</pre>
  
Below is a demonstration of how to use these methods to create a new general project with SWTBot.
+
Now the main shell can be brought into focus before any call to ''bot.menu(String)''. However, doing so may be tedious and error-prone, so use the following helper method instead when clicking on main menu items:
  
 
<pre>
 
<pre>
@Test
+
/**
public void testCreateProject() {
+
  * Click an item from the main Eclipse menu, with a guarantee that the main
// Open the "New Project" wizard, which features a tree & a text search bar
+
  * shell will be in focus.
bot.menu("File").menu("New").menu("Project...").click();
+
  * @param items The names of each item in the path to the target item to click.
bot.shell("New Project").setFocus();
+
  * For example, to click "File->New->Project...", the items would be "File",
 
+
  * "New", and "Project...".
// Want to create a general project, so search for the "Project" node
+
  */
bot.text().setText("Project");
+
public static void clickMainMenu(String... items) {
 
+
    if (items.length == 0) {
// Wait for the node to be revealed, knowing that its parent is the "General" node
+
        return;
bot.waitUntil(new NodeAvailableAndSelect(bot.tree(), "General", "Project"));
+
    }
 
+
    mainShell.setFocus();
// Performing the wait condition selected the node, so we can now navigate through the wizard
+
    SWTBotMenu menu = bot.menu(items[0]);
bot.button("Next >").click();
+
    for (int i = 1; i < items.length; i++) {
bot.textWithLabel("Project name:").setText("My New Project");
+
        menu = menu.menu(items[i]);
bot.button("Finish").click();
+
    }
 +
    menu.click();
 
}
 
}
 
</pre>
 
</pre>
  
= Radio Button Selection Problems =
+
= Minor Scenarios =
 
+
== Description ==
+
 
+
SWTBot is unable to properly select a radio button if another button in its group is already selected. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=344484 for details.
+
 
+
== Symptoms ==
+
 
+
* Tests that click on a non-selected radio button behave as if it were never clicked
+
* Tests that step through clicking each radio button in a group only succeed with tests on the button that was clicked first
+
 
+
== Workaround ==
+
 
+
In order to select a radio button, no other button in the group can be selected. If the index of a pre-selected button is known, you must first de-select it by calling this helper method:
+
 
+
<pre>
+
/**
+
* Deselects a radio button.
+
* Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=344484
+
* @param currSelection The index of the radiobutton to deselect
+
*/
+
private void deselectDefaultSelection(final int currSelection) {
+
UIThreadRunnable.syncExec(new VoidResult() {
+
@Override
+
public void run() {
+
@SuppressWarnings("unchecked")
+
Matcher<Widget> matcher = allOf(widgetOfType(Button.class), withStyle(SWT.RADIO, "SWT.RADIO"));
+
Button b = (Button) bot.widget(matcher, currSelection);
+
b.setSelection(false);
+
}
+
});
+
}
+
</pre>
+
  
After calling this method, clicking on a radio button will work as expected. Make sure to call this method whenever you want to change the selected radio button.
+
* If finding a view with ''bot.viewByTitle(String)'' doesn't work, try ''bot.viewByPartName(String)'' instead.
 +
* When attempting to click on an item from a drop down button menu, you may get a "Widget not found" exception. To avoid this, activate the shell containing the button (with ''bot.activate(String)'') before accessing the drop down menu.

Latest revision as of 06:00, 13 January 2022

{{#eclipseproject:tools.linuxtools}}

Linux Tools
Website
Download
Community
Mailing ListForumsIRCmattermost
Issues
OpenHelp WantedBug Day
Contribute
Browse Source

When creating SWTBot Tests for Linux Tools projects, developers may experience unusual or unexpected test failures. Listed on this page are some common SWTBot issues known to affect Linux Tools SWTBot tests, and workarounds for them until they are directly fixed by SWTBot.

Support for SWTBot itself is available here.

Main Menu Items Not Found

Description

When trying to access a menu item from the main Eclipse shell with bot.menu(String), a WidgetNotFound exception may be thrown. An example case of this is accessing the File menu with bot.menu("File"). The reason this exception occurs is because the main shell must be active whenever a menu item is accessed; otherwise, the menu widget will not be seen by the bot.

Symptoms

  • Menus can be clicked at certain points in the test, but not others
  • A menu is clicked on to open a dialog shell, but after that shell is closed, another attempt to access a menu item fails

A likely cause of these symptoms is the loss of focus of the main shell after certain operations, especially the appearance of new shells.

Workaround

As the main Eclipse shell must be active before a menu item is accessed, the main shell should be captured and stored in a field variable so that it can be brought into focus at any time. Call the following method at the beginning of a test class (preferably at the start of a @BeforeClass method) to safely capture the shell:

public static void getMainShell() {
    SWTWorkbenchBot bot = new SWTWorkbenchBot();
    mainShell = null;  // statically defined elsewhere

    for (int i = 0, attempts = 100; i < attempts; i++) {
        for (SWTBotShell shell : bot.shells()) {
            if (shell.getText().contains("Eclipse Platform")) {
                mainShell = shell;
                shell.setFocus();
                break;
            }
        }
    }
}

Now the main shell can be brought into focus before any call to bot.menu(String). However, doing so may be tedious and error-prone, so use the following helper method instead when clicking on main menu items:

/**
  * Click an item from the main Eclipse menu, with a guarantee that the main
  * shell will be in focus.
  * @param items The names of each item in the path to the target item to click.
  * For example, to click "File->New->Project...", the items would be "File",
  * "New", and "Project...".
  */
public static void clickMainMenu(String... items) {
    if (items.length == 0) {
        return;
    }
    mainShell.setFocus();
    SWTBotMenu menu = bot.menu(items[0]);
    for (int i = 1; i < items.length; i++) {
        menu = menu.menu(items[i]);
    }
    menu.click();
}

Minor Scenarios

  • If finding a view with bot.viewByTitle(String) doesn't work, try bot.viewByPartName(String) instead.
  • When attempting to click on an item from a drop down button menu, you may get a "Widget not found" exception. To avoid this, activate the shell containing the button (with bot.activate(String)) before accessing the drop down menu.

Back to the top