eclipse summit europe '10 - test ui aspects of plug-ins

21
PR0031 - 2010-11-01 Redistribution and other use of this material requires written permission from The RCP Company. Test UI Aspects of Plug-ins Testing the UI of an Eclipse plug-in is usually considered rather difficult and something that is best left for specialized tools. Also, the test is often considered very fragile and is expected to be updated whenever you make even the smallest change to your UI. But that need not be so. By using a few rather simple tools and a few just as rules, you can test all the UI parts of an application... This presentation was made for Eclipse Summit Europe 2010.

Upload: tonny-madsen

Post on 11-Nov-2014

2.884 views

Category:

Technology


2 download

DESCRIPTION

Testing the UI of an Eclipse plug-in is usually considered rather difficult and something that is best left for specialized tools. Also, the test is often considered very fragile and is expected to be updated whenever you make even the smallest change to your UI. But that need not be so. By using a few rather simple tools and a few just as rules, you can test all the UI parts of an application... This presentation was made for Eclipse Summit Europe 2010.

TRANSCRIPT

Page 1: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

Redistribution and other use of this material requires written permission from The RCP Company.

Test UI Aspects of Plug-ins

Testing the UI of an Eclipse plug-in is usually considered rather difficult and something that is best left for specialized tools. Also, the test is often considered very fragile and is expected to be updated whenever you make even the smallest change to your UI.But that need not be so. By using a few rather simple tools and a few just as rules, you can test all the UI parts of an application...

This presentation was made for Eclipse Summit Europe 2010.

Page 2: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0029 - 2010-05-31

2

About Me

Tonny Madsen, Founder and Owner of The RCP Company

20 years of experience in system development in major companies 9 years experience as the Systems Architect of an 20+ MLoC project 8 years of experience with Eclipse and Eclipse RCP

Solutions Member of the Eclipse Foundation Chairman of Eclipse.dk Extern Lecturer at IT-University on Model Driven Development and

Domain Specific Languages Regular speaker at EclipseCon, Eclipse Summit, etc

Page 3: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

3

Downloads

This presentation makes some use of a library of low-level test methods.

These can be downloaded from

http://rcp-company.com/uploads/materials/ESE-2010/TestPlugins-2010-11-01.zip

These slides are also available as

http://rcp-company.com/uploads/materials/ESE-2010/PR0031 - Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins.pdf

Page 4: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

4

JUnit Support in Eclipse

Both JUnit 3 and 4 are supported in Eclipse 3.4 Alternatively use TPTP Testing framework

Special Launch types for “JUnit” and “JUnit Plug-in Test”

Special JUnit view Can create new Mylyn tasks from failures

It is possible to add plug-ins in Eclipse IDE that will be notified of JUnit runs and results

Can be used to ensure that tests all run before commits

Page 5: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

5

Where to put Tests

Tests of plug-ins can be put several places each with separate pros and cons

Inline in the application plug-ins Pros: Easy to manage, access to everything Cons: In the final product

In separate plug-ins Pros: Separate from the product Cons: Only access to the exported interface

In attached fragments Pros: Access to everything, separate from the product Cons: A different “thing” from plug-ins, difficult to test via PDEbuild

Page 6: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

6

What can be Tested using JUnit

Almost everything! Functional APIs Behavior of UI elements Performance

It is primary the look of the UI that cannot be tested To do this, use special UI testing tools Known SWT aware tools

QF-Test GUIdancer WindowTester

But remember SWT is mostly just a thin layer on top of the native widget set, so normally the native UI testers can be used as well

A few Eclipse elements can be very difficult to test and will require extra co-operation from the tested code

Dialogs Wizards Basically everything that creates a new event loop

Page 7: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

7

Testing with JUnit 4

Create a new plug-in or fragment Add dependency on “org.junit4” Create a test class

Alternatively use JUnit Test Case wizard Annotate test methods with @Test Annotate common setup and clean-up code with

@Before and @After: Will be executed for each test in class @BeforeClass and @AfterClass: Will be executed once per class

public class ManagerSizesTest {private Manager m;

@Beforepublic void setup() {

m = Manager.getManager();}

@Testpublic void testAttributeProviders() {

assertEquals(true, m.isReady());}

}

Page 8: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

8

Testing Perspectives, Views and Editors

Perspectives IWorkbenchWindow.openPage(String perspectiveId, IAdaptable input) Command org.eclipse.ui.perspectives.showPerspective

Editors IDE.openEditor(IWorkbenchPage page, IFile file)

One of a large number of methods IWorkbenchPage.findEditor(IFile file) No specific command

Views IWorkbenchPage.showView(String id)

Will open the view in the site according to the perspective definition Command org.eclipse.ui.views.showView

Page 9: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

9

Testing Interaction

UI tests often have to interact with the application in a manner that is identical or at least similar to the interaction by a user

Several way to interact Directly via generated events – especially mouse and key related events Indirectly via manipulation of SWT widgets Indirectly via commands Indirectly via handlers

Which way to use often depends on the level of knowledge of the application implementation permitted by the tester

In all cases you also need to handle the event loop as tests often runs in the event thread

Page 10: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

10

Test Interaction – Mouse and Key

A subset of generated mouse and key events can be handled via Display.post(Event)

KeyDown, KeyUp Key down and up must be paired Modifiers must be “pressed” separately Textual descriptions of key strokes can be converted to key codes via KeyStroke.getInstance(stroke)

MouseDown, MouseUp MouseMove

Mouse must be moved before “pressed” Double-click is handled by clicking twice

MouseWheel

Page 11: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

11

Test Interaction – Mouse and Key

public static void postMouse(Control c, Point p) {final Point pt = c.getDisplay().map(c, null, p);

final Event e = new Event();e.type = SWT.MouseMove;e.x = pt.x;e.y = pt.y;assertTrue(c.getDisplay().post(e));yield();

e.type = SWT.MouseDown;e.button = 1;e.count = 1;assertTrue(c.getDisplay().post(e));yield();

e.type = SWT.MouseUp;e.button = 1;e.count = 1;assertTrue(c.getDisplay().post(e));yield();

}

Page 12: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

12

Test Interaction – The Event Thread

If the test runs in the event thread, event dispatching can be needed. Required after use of Display.post(Event)

To dispatch all events in the event queue use (often known as yield)

To dispatch all paint requests for a control – possible children

To wait a certain period while dispatching events use

while (display.readAndDispatch()) {}

cont = false;display.timerExec(msec, new Runnable() {

@Overridepublic void run() {

cont = true;}

});while (!cont) {

if (!display.readAndDispatch()) {display.sleep();

}}

control.update();

Page 13: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

13

Test Interaction – Direct Manipulation of Widgets

A lot of testing can be done by manipulating widgets directly Cons: it requires an intimate knowledge of the application Pros: it is very robust to many types of changes in the application

public class TestView extends ViewPart {public Text myText;

@Overridepublic void createPartControl(Composite parent) {

Composite top = new Composite(parent, SWT.NONE);top.setLayout(new GridLayout(1, false));

myText = new Text(top, SWT.SINGLE | SWT.LEAD | SWT.BORDER);myText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));myText.setText("");

}

@Overridepublic void setFocus() {}

}

Page 14: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

14

Test Interaction – Direct Manipulation of Widgets

public class TestViewTest {private TestView myView;

@Beforepublic void before() {

try {IWorkbenchPage page = PlatformUI.getWorkbench().

getActiveWorkbenchWindow().getActivePage();myView = (TestView) page.showView("com.rcpcompany.appl.views.TestView");assertNotNull(myView);

} catch (final Exception ex) {fail(ex.getMessage());

}}

@Testpublic void testText() {

myView.myText.setText("hello");// Testing the result…

}}

Page 15: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

15

Test Interaction – Direct Manipulation of Widgets

Some often used cases Entering characters into a text widget: Text.setText(str) Selecting item in combo box: Combo.setText(str) or Combo.select(i) Ticking check boxes and radio buttons: Button.setSelection(b)

But not push buttons! Moving scrollbars, sliders, and scales: ScrollBar.setSelection(i) Changing a tab in a tab folder: TabFolder.setSelection(i)

Though no selection event is posted

Page 16: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

16

Test Interaction – Executing Simple Commands

A simple command has no parameters

IHandlerService hs = …;

hs.executeCommand("<command-id>", null);

Page 17: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

17

Test Interaction – Executing Parameterized Commands

A parameterized command has one or more parameters and can be created in one of two ways:

IHandlerService hs = …;ICommandService commandService = …;

Command c = commandService.getCommand("<command-id>");IParameter param = c.getParameter("<parameter-id>");Parameterization[] parms = new Parameterization[] { new Parameterization(param, "<value>") };

ParameterizedCommand pc = new ParameterizedCommand(c, parms);

hs.executeCommand(pc, null);

IHandlerService hs = …;ICommandService commandService = …;

ParameterizedCommand pc = commandService.deserialize(”<cmd-id>(<p-id>=<value>)");hs.executeCommand(pc, null);

ParameterizedCommand pc = commandService.deserialize(”org.eclipse.ui.views.showView(“ +

“org.eclipse.ui.views.showView.viewId=org.eclipse.ui.views.ContentOutline)");

Page 18: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

18

Testing Tables

Tables can be a little more difficult to manage

Finding the bounds of a specific cell: Table.getItem(row).getBounds(column) Finding the bounds of a specific header:

Adjust y to 0 and height to Table.getHeaderHeight()

If sorting a table, sleep for at least 5-600ms

The row element for a specific row in a viewer: Table.getItem(row).getData()

Page 19: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

19

Parameterized Tests

It can be very beneficial to parameterize UI tests Test data can even be generated

@RunWith(Parameterized.class)public class UIAttributeFactoryTest<T extends Widget> extends BaseUIAttributeFactoryTest<T> {

@Parameterspublic static Collection<Object[]> data() {

return Arrays.asList(new Object[][] {{ Button.class, SWT.PUSH, "", String.class, "text" },{ Button.class, SWT.PUSH, "text", String.class, "text" },{ Button.class, SWT.PUSH, "background", Color.class, "background" },…

});}

public UIAttributeFactoryTest(Class<T> widgetType, int style, final String attribute,final Class<?> expectedValueType, String property) {

...}

@Testpublic void test() {

…}

}

Page 20: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

20

Testing no Error Messages are Logged

Most parts of the Eclipse RCP framework log errors using the log interface of plug-ins

To test that no error messages are logged hook into the Platform log listener interface

public static void assertNoLog(Runnable run) {final NoLogListener ll = new NoLogListener();Platform.addLogListener(ll);try {

run.run();} catch (final Exception ex) {

fail("Exception occured: " + ex.getClass() + ": " + ex.getMessage());}Platform.removeLogListener(ll);assertTrue("Log message: " + ll.lastMessage, ll.called == 0);

}

private static class NoLogListener implements ILogListener {public int called = 0;public String lastMessage;

public void logging(IStatus status, String plugin) {if (status.getSeverity() != IStatus.ERROR) return;called++;lastMessage = status.getMessage();

}}

Page 21: Eclipse Summit Europe '10 - Test UI Aspects of Plug-ins

PR0031 - 2010-11-01

21

If You Want to Know More about Testing

“JUnit 4 in 60 Seconds” http://www.cavdar.net/2008/07/21/junit-4-in-60-seconds/

Short but very concise and with focus on the important stuff “JUnit.org”

http://www.junit.org/ Home of all the xUnit technologies

“List of GUI testing tools” http://en.wikipedia.org/wiki/List_of_GUI_testing_tools