Swing's Event Dispatch Thread (EDT)

The cardinal rule of Swing threading states that all access to all Swing components should be done in the event dispatch thread (EDT). To avoid unexpected behavior in your GUI tests (e.g. random test failures), this rule also applies to test code.

If you follow these tips you ensure that your GUI tests respect Swing's threading rules:

  • Read about Swing's threading rules. Keep in mind the cardinal rule
  • Creation and any direct access to Swing components should be done via GuiActionRunner using a GuiQuery or GuiTask, because JUnit and TestNG tests do not run on the EDT. More details below on this page.
  • Access of Swing components through AssertJ Swing APIs is already EDT-safe.
  • It is strongly recommended to use FailOnThreadViolationRepaintManager to catch EDT-access violations. More details below on this page.

Alex Ruiz wrote an entry on his blog about how to write EDT-safe GUI tests.

AssertJ Swing performs all access to Swing components in the EDT. AssertJ Swing also exposes a convenient mechanism to access Swing components in the EDT from your test code. This mechanism involves one (with lambda expressions) to three (traditional way) classes:

  • GuiQuery*, for performing actions in the EDT that return a value
  • GuiTask*, for performing actions in the EDT that do not return a value
  • GuiActionRunner, executes a GuiQuery or GuiTask (or Callable/Runnable via lambda expressions) in the EDT, rethrowing any exceptions thrown when executing any GUI action in the EDT.

* If you use lambda expressions you don't need to use this class directly.

Examples

When you would like to read the text of a label, execute the following code:

final JLabel nameLabel = ... // get a reference to a JLabel
String text = GuiActionRunner.execute(() -> nameLabel.getText());

When you would like to set the text of a label, execute:

final JLabel nameLabel = ... // get a reference to a JLabel
GuiActionRunner.execute(() -> nameLabel.setText("Name:"));
Note
In some cases the lambda expression does not work. You can always use the above examples with anonymous or dedicated subclasses of GuiQuery and GuiTask.

AssertJ Swing provides the class FailOnThreadViolationRepaintManager that forces a test failure if access to Swing components is not performed on the EDT. This repaint manager is based on ThreadCheckingRepaintManager by Scott Delap and Alex Potochkin. For more details about how to check if GUI component is done outside the EDT, please check Alex Potochkin's article Debugging Swing, the final summary.

Installing FailOnThreadViolationRepaintManager is pretty simple. The following example shows how to install it in the class-level setup method of a JUnit test:

@BeforeClass
public static void setUpOnce() {
  FailOnThreadViolationRepaintManager.install();
}

When using Sun's JVM, a new instance of FailOnThreadViolationRepaintManager will be set as the default repaint manager in Swing once and only once, regardless of the number of times install() is called. On other JVMs this optimization is not guaranteed.

Once a FailOnThreadViolationRepaintManager is installed, it will throw an EdtViolationException if a GUI test is not accessing Swing components in the EDT.