The Workbench Test Framework
Author: Build

## The Workbench Test Suite

Dave Springgay
September 2001

### In Brief

This document describes the UI Test Suite. This test suite is available from `org.eclipse.ui.tests` in the desktop repository and consist of a series of non-interactive sniff tests which are run after a build, plus a set of interactive tests which require human feedback. You can run any of these from the JUnit Eclipse Plugin Tests launcher or from the command line.

The `org.eclipse.ui.tests` project is organized in hierarchical fashion. The root is `UiTestSuite` in `org.eclipse.ui.tests`. This test suite contains a collection of "specialized suites" which test specific areas of functionality or components in the workbench. Currently there is only one suite, `ApiTestSuite` in`org.eclipse.ui.tests.api`, which contains a number of test cases which deal specifically with workbench API. A `uiTest` extension is declared for each suite so that you can run every test in the workbench or a subset of the tests.

To run the UiTestSuite from within Eclipse just select UiTestSuite.java in the navigator and invoke Run > JUnit Eclipse Plugin Tests. The results of the test suite will appear in the JUnit view.

### Test Patterns

In our own testing we have discovered a number of common test patterns. In order to encourage a consistent approach for testing they are published below.

Simple Setters, Getters and Commands

Scenario: You want to test setters, commands and getters on an interface.

Method: Call the setter or command which affects the object state. Call the getter to verify that state.

Top Down Coverage

Scenario: You want to demonstrate thorough coverage of a component.

Method: Start at the object root of the instance hierarchy and test every class downwards to the leaf classes. Stop when you encounter a layer which already has JUnit test cases. For instance, in the workbench UI don't test JFace, SWT, or core. They should have their own test suites and are assumed to work.

Superclass Subclass

Scenario: You want to test D, which is a subclass of B.

Method: Implement a test case for B called BTest. Then create a subclass of BTest called DTest which tests D. If B is an abstract class use a factory method in BTest to create the test object.

Listener Source

Scenario: You want to test S, a class which fires events when a particular situation occurs.

Method: Implement a listener for S which records the reception of events. Then write a test class for S called STest which does something which should cause those events to fire. Verify the reception of events afterwards.

Multiple Session

Scenario: You want to test the persistance of state from one session to the next.

Method: You need to create two test suites. One test suite will set up the state. The other will verify the state. Run them sequentially in two separate processes.

Global State

Scenario: In Eclipse the workbench is a global object. Unfortunately, this means that one test case may modify that state and affect the outcome of another unrelated test case. How can you avoid this problem?

Method: If the test case modifies the state of a window or something in the window you should create a new window as part of the setUp for the test case. Run the test code within that window and then close the test window in the tearDown method. The modified state will be discarded when the window is closed

Lifecycle

Scenario: Within the workbench there are various interfaces, such as IViewPart, which are defined as API and implemented by plugin code. There is no need to test the implementation of the interface, but it is good to test the lifecycle as implemented by objects which call the interface.

Method: Define a class X which implements the interface and records the invocation of various methods. Create a scenario where this class is loaded and should receive events. Afterwards, test that those methods were called.

Piercing the Encapsulation

Scenario: To test the behavior of commands which modify the state of the object when there are no public interfaces to query that state.

Method: If possible, cast the interface to a concrete class with additional public methods. For instance, in the workbench the underlying structure for IWorkbench is exposed in Workbench. Given a Workbench object, you can get the menu, toolbar, etc, and interact directly with the actions to verify their state or invoke them directly. This is also a useful way to simulate action invocation from the UI.

Mock Objects

Scenario: To test the implementation of an interface which instantiates an extension. For instance, in the test case for IWorkbenchPage we need to open views and editors.

Method: If we reference views and editors which exist within the Workbench UI Standard Components project the test case is vulnerable to change in those components. In this case we're not testing the components, we're testing IWorkbenchPage, so we implemented some light weight mock views and editors which do nothing more than record their own creation and lifecycle.