Reader small image

You're reading from  Eclipse Plug-in Development Beginner's Guide - Second Edition

Product typeBook
Published inAug 2016
Reading LevelExpert
Publisher
ISBN-139781783980697
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
Alex Blewitt
Alex Blewitt
author image
Alex Blewitt

contacted on 30 aug 16 _____________ Dr Alex Blewitt has over 20 years of experience in Objective-C and has been using Apple frameworks since NeXTstep 3.0. He upgraded his NeXTstation for a TiBook when Apple released Mac OS X in 2001 and has been developing on it ever since. Alex currently works for an investment bank in London, writes for the on-line technology news site InfoQ and has published two other books for Packt publishing. He also has a number of apps on the Apple AppStore through Bandlem Limited. When he's not working on technology, and if the weather is nice, he likes to go flying from the nearby Cranfield airport. Alex writes regularly at his blog, http://alblue.bandlem.com, as well tweeting regularly from Twitter as @alblue. Acknowledgements This book would not have been possible without the ongoing love and support of my wife Amy, who has helped me through both the highs and lows of life. She gave me the freedom to work during the many late nights and weekends that it takes to produce a book and its associated code repository. She truly is the Lem of my life. I'd also like to thank my parents, Ann and Derek, for their encouragement and support during my formative years. It was this work ethic that allowed me to start my technology career as a teenager and to incorporate my first company before I was 25. I'd also like to congratulate them on their 50th wedding anniversary in 2015, and I look forward to reaching that goal with Amy. Thanks are due especially to the reviewer of this version of the book: Antonio Bello, as well as the previous version of this book: Nate Cook, James Robert and Arvid Gerstmann, who provided excellent feedback on the contents of this book during development and caught many errors in both the text and code. Any remaining errors are my own. I'd also like to thank my children Sam and Holly for inspiring me and hope that they too can achieve anything that they set their minds to. Finally, I'd like to thank Ben Moseley and Eren Kotan, both of whom introduced me to NeXT in the first place and set my career going on a twenty year journey to this book.
Read more about Alex Blewitt

Right arrow

Chapter 11. Automated Testing of Plug-ins

JUnit and SWTBot – automated testing of plug-ins

JUnit is the testing framework of choice for Eclipse applications, and can be used to run either pure Java tests or plug-in tests. If user interfaces need to be exercised, then SWTBot provides a facade onto the underlying Eclipse application, and can be used to drive menus, dialogs, and views.

In this chapter, we will:

  • Create a JUnit test running as pure Java code

  • Create a JUnit test running as a plug-in

  • Write a UI test using SWTBot

  • Interrogate views and work with dialogs

  • Wait for a condition to occur before continuing

Using JUnit for automated testing


One of the original automated unit testing frameworks, JUnit has been in use at Eclipse for over a decade. Part of Eclipse's quality can be attributed to the set of automated unit tests that exercise both the UI and the non-UI (headless) components.

JUnit works by creating a test case with one or more tests—which usually correspond to a class and methods respectively. Conventionally, test classes end with Test but this is not a requirement. Multiple test cases can be aggregated into test suites, although implicitly a project becomes its own test suite.

Time for action – adding dependencies to the target platform


The target platform created in Chapter 10, Target Platforms, contained the necessary dependencies to build the plug-ins, but not to test them. To use the test cases in this platform, they need to be added. If the target platform isn't being used, just install SWTBot from the main update site; SWTBot has been part of the default Eclipse repository since Eclipse Mars.

  1. Open the com.packtpub.e4.target.mars.target platform definition.

  2. On the Definition tab, click on the Mars repository, and then click on Edit. This will allow other features to be added.

  3. Search for SWTBot and add SWTBot for Eclipse Testing, SWTBot for SWT Testing, and SWTBot IDE Features. Click on Finish to update the target platform:

What just happened?

In order to use JUnit and SWTBot, they need to be added to the target platform. JUnit is part of the standard Eclipse installations, but if a target platform is being used, it won't necessarily be made available.

The SWTBot...

Time for action – writing a simple JUnit 4 test case


This part explains how to write and run a simple JUnit 4 test case in Eclipse.

  1. Create a new Java project called com.packtpub.e4.junit.example.

  2. Create a class called MathUtil in com.packtpub.e4.junit.example.

  3. Create a public static method called isOdd that takes an int and returns a boolean if it is an odd number (using value % 2 == 1).

  4. Create a new class called MathUtilTest in a package com.packtpub.e4.junit.example.

  5. Create a method called testOdd with an annotation @Test, which is the way JUnit 4 signifies that this method is a test case.

  6. Click on the quick-fix to Add JUnit 4 library to the build path, or edit the build path manually to point to Eclipse's plugins/org.junit_4.*.jar.

  7. Implement the testOdd method as follows:

    assertTrue(MathUtil.isOdd(3));
    assertFalse(MathUtil.isOdd(4));
  8. Add an import static of org.junit.Assert.* to fix the compiler errors.

  9. Right-click on the project and choose Run As | JUnit Test, and the JUnit test view should be...

Time for action – writing a plug-in test


Although Java projects and Java plug-in projects both use Java and JUnit to execute, plug-ins typically need to have access provided by the runtime platform, which is only available if running in an OSGi or Eclipse environment.

  1. Create a new plug-in project called com.packtpub.e4.junit.plugin.

  2. Create a new JUnit test called PlatformTest in the com.packtpub.e4.junit.plugin package.

  3. Create a method, testPlatform, which ensures that the Platform is running:

    @Test
    public void testPlatform() {
      assertTrue(Platform.isRunning());
    }
  4. Click on the quick-fix to add org.junit to the required bundles.

    1. Alternatively, open up the project's manifest by right-clicking on it and choosing Plug-in Tools | Open Manifest.

    2. Go to the Dependencies tab, click on Add, and select org.junit from the dialog.

    3. Ensure that org.eclipse.core.runtime is also added as a dependency.

  5. Run the test by right-clicking on the project, choosing Run As | JUnit Test and seeing the error message fail with...

Using SWTBot for user interface testing


SWTBot is an automated testing framework that allows the Eclipse user interface and SWT applications to be tested in place. Although writing tests and exercising the models behind an application can be essential, sometimes it is necessary to test the interaction of the user interface itself.

Time for action – writing an SWTBot test


The first step is to install SWTBot from the Eclipse update site. These examples were tested with http://download.eclipse.org/technology/swtbot/releases/latest/ version 2.3.0, but check out the book's errata for up-to-date information.

  1. Go to Help | Install New Software and enter the SWTBot update site.

  2. Select everything except the GEF feature:

  3. Click on Next to install.

  4. Restart Eclipse when prompted.

  5. Add the following bundle dependencies to the plug-in manifest for the com.packtpub.e4.junit.plugin project:

    1. org.eclipse.swtbot.junit4_x

    2. org.eclipse.swtbot.forms.finder

    3. org.eclipse.swtbot.eclipse.finder

    4. org.eclipse.ui

  6. Create a class called UITest in the com.packtpub.e4.junit.plugin package.

  7. Add a class annotation @RunWith(SWTBotJunit4ClassRunner.class).

  8. Create a method called testUI and with an annotation @Test.

  9. Inside the testUI method, create an instance of SWTWorkbenchBot.

  10. Iterate through the bot's shells and assert that the one that is visible has a title...

Time for action – working with menus


Note that SWTBot works on a non-UI thread by default to avoid deadlock with modal dialogs and other user interface actions. If the tests need to interact with specific SWT widgets, it is necessary to invoke a Runnable via the UI thread.

To make this easier, the SWTBot framework has several helper methods that can provide a facade of the workspace, including the ability to click on buttons and show menus.

  1. Create a new test method in the UITest class called createProject with a @Test annotation.

  2. Create a new SWTWorkbenchBot instance.

  3. Use the menu method of the bot to navigate the File | Project... menus, and perform a click.

  4. Use the shell method of the bot to get the newly opened shell with a title of New Project. Activate the shell to ensure that it has focus.

  5. Use the tree method of the bot to find a tree in the shell, and expandNode the General node, and finally select the Project.

  6. Invoke the Next > button with a click. Note the space between the Next and...

Working with SWTBot


There are some techniques that help when writing SWTBot tests, such as organizing the test code and hiding the welcome screen at start up, which otherwise might distort the test run.

Time for action – hiding the welcome screen


When Eclipse starts, it typically displays a welcome page. Since this often gets in the way of automated user testing, it is useful to close it at startup.

  1. In the createProject method, within a try block, obtain a view with the title Welcome.

  2. Invoke the close method.

  3. The code will change to look like this:

    SWTWorkbenchBot bot = new SWTWorkbenchBot();
    try {
      bot.viewByTitle("Welcome").close();
    } catch (WidgetNotFoundException e) {
      // ignore
    }
  4. Run the test, and the welcome screen should be closed before the test is run.

What just happened?

Upon startup, the IDE will show a welcome screen. This is shown in a view with a Welcome title.

Using the viewByTitle accessor, the (SWTBot wrapper) view can be accessed. If the view doesn't exist, then an exception will be thrown; so for safety, check and catch any WidgetNotFoundException, since not finding the welcome screen is not a failure.

Having found the welcome page, invoking the close method will close the...

Time for action – avoiding SWTBot runtime errors


Once more test methods are added, the runtime may start throwing spurious errors. This is because the order of the tests may cause changes, and ones that run previously may modify the state of the workbench. This can be mitigated by moving common setup and tear-down routines into a single place.

  1. Create a static method beforeClass.

  2. Add the annotation @BeforeClass from the org.junit package.

  3. Move references to creating a SWTWorkbenchBot to the static method, and save the value in a static field.

  4. The code looks like:

    private static SWTWorkbenchBot bot;
    @BeforeClass
    public static void beforeClass() {
      bot = new SWTWorkbenchBot();
      try {
        bot.viewByTitle("Welcome").close();
      } catch (WidgetNotFoundException e) {
        // ignore
      }
    }
  5. Run the tests and ensure that they pass appropriately.

What just happened?

The JUnit annotation @BeforeClass allows a single static method to be executed prior to any of the tests running in the class. This is used to...

Working with views


As with menus and dialogs, views that have been created can be interrogated with SWTBot as well.

Time for action: showing views


To show other views, the same mechanism is done in the UI tests as a user would do, by navigating the Window | Show View | Other… menu.

  1. Create a new method, testTimeZoneView, with an @Test annotation.

  2. From the bot, open the Window | Show View | Other… dialog.

  3. Get the shell with the title Show View and activate it.

  4. Expand the Timekeeping node and select the Time Zone View node (the view created in Chapter 2, Creating Views with SWT).

  5. Click on the OK button to have the view shown.

  6. Use the bot.viewByTitle() method to acquire a reference to the view.

  7. Assert that the view is not null.

  8. The code looks like:

    @Test
    public void testTimeZoneView() {
      bot.menu("Window").menu("Show View").menu("Other...").click();
      SWTBotShell shell = bot.shell("Show View");
      shell.activate();
      bot.tree().expandNode("Timekeeping").select("Time Zone View");
      bot.button("OK").click();
      SWTBotView timeZoneView = bot.viewByTitle("Time Zone View");
      assertNotNull(timeZoneView);
    }
  9. Run the tests...

Time for action – interrogating views


Having been able to acquire a reference to the view, the next step is to deal with specific user interface components. For standard controls such as Button and Text, the bot provides standard methods to acquire. To get hold of other components, the widget hierarchy will have to be interrogated directly.

  1. In the testTimeZoneView method, get the Widget from the returned SWTBotView.

  2. Create a Matcher using the WidgetMatcherFactory to find widgetsOfType(CTabItem.class).

  3. Use the bot.widgets method to search for a list of CTabItem instances in the view's widget.

  4. Ensure that the number of elements returned is equal to the number of time zone regions.

  5. The code looks like:

    SWTBotView timeZoneView = bot.viewByTitle("Time Zone View");
    assertNotNull(timeZoneView);
    Widget widget = timeZoneView.getWidget();
    org.hamcrest.Matcher<CTabItem> matcher =
      WidgetMatcherFactory.widgetOfType(CTabItem.class);
    final java.util.List<? extends CTabItem> ctabs = 
      bot.widgets...

Interacting with the UI


Care needs to be taken which thread the user interface is interrogated from. This section will show how to obtain values and wait for asynchronous results to be delivered by the workbench.

Time for action – getting values from the UI


If the test tries to access a property from the returned widget, there will be an exception thrown. For example, ctabs.get(0).getText() will result in an Invalid thread access SWT error.

To perform testing on widgets, the code has to run in the UI thread. Either the Display.getDefault().syncExec() or the equivalent Synchronizer class can be used, but SWTBot has a UIThreadRunnable that can launch code and a general interface called StringResult, which is like a Runnable that can return a String value through syncExec.

  1. At the end of the testTimeZone method of the UITest class, create a new StringResult and pass it to UIThreadRunnable.syncExec().

  2. In the run method, get the first CTabItem and return its text value.

  3. After the Runnable method has run, assert that the value is Africa.

  4. The code looks like:

    String tabText = UIThreadRunnable.syncExec(new StringResult() {
      @Override
      public String run() {
        return ctabs.get(0).getText();
      }
    });
    assertEquals...

Time for action – waiting for a condition


Typically an action may require some result to happen in the user interface before testing can continue. Since the SWTBot can run much faster than a human can, waiting for the result of an action may be necessary. To demonstrate this, create a Java project with a single source file and then use the conditions to wait until the class file is compiled.

  1. Create a new method in the UITest class called createJavaProject.

  2. Use the bot to create a new Java project by copying the createProject method as a template.

  3. Add the org.eclipse.core.resources as a dependency to the plug-in.

  4. Add a method getProject, which takes a projectName and returns an IProject from ResourcesPlugin.getWorkspace().getRoot().getProject().

  5. At the end of the createJavaProject method, use the getProject method with the test project to get the folder src.

  6. If the folder does not exist, create it.

  7. Get the file from src called Test.java.

  8. Create it with the contents from class Test{} bytes as a ByteArrayInputStream...

Summary


Being able to test code automatically is a key part of creating quality software. Whether the tests exercise the underlying models or the user interface—or ideally a combination of both—more tests help highlight problems that occur when changes to the underlying framework happen, or when dependencies change and introduce unwanted side-effects.

The next chapter will show how to integrate everything with an automated build.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Eclipse Plug-in Development Beginner's Guide - Second Edition
Published in: Aug 2016Publisher: ISBN-13: 9781783980697
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Alex Blewitt

contacted on 30 aug 16 _____________ Dr Alex Blewitt has over 20 years of experience in Objective-C and has been using Apple frameworks since NeXTstep 3.0. He upgraded his NeXTstation for a TiBook when Apple released Mac OS X in 2001 and has been developing on it ever since. Alex currently works for an investment bank in London, writes for the on-line technology news site InfoQ and has published two other books for Packt publishing. He also has a number of apps on the Apple AppStore through Bandlem Limited. When he's not working on technology, and if the weather is nice, he likes to go flying from the nearby Cranfield airport. Alex writes regularly at his blog, http://alblue.bandlem.com, as well tweeting regularly from Twitter as @alblue. Acknowledgements This book would not have been possible without the ongoing love and support of my wife Amy, who has helped me through both the highs and lows of life. She gave me the freedom to work during the many late nights and weekends that it takes to produce a book and its associated code repository. She truly is the Lem of my life. I'd also like to thank my parents, Ann and Derek, for their encouragement and support during my formative years. It was this work ethic that allowed me to start my technology career as a teenager and to incorporate my first company before I was 25. I'd also like to congratulate them on their 50th wedding anniversary in 2015, and I look forward to reaching that goal with Amy. Thanks are due especially to the reviewer of this version of the book: Antonio Bello, as well as the previous version of this book: Nate Cook, James Robert and Arvid Gerstmann, who provided excellent feedback on the contents of this book during development and caught many errors in both the text and code. Any remaining errors are my own. I'd also like to thank my children Sam and Holly for inspiring me and hope that they too can achieve anything that they set their minds to. Finally, I'd like to thank Ben Moseley and Eren Kotan, both of whom introduced me to NeXT in the first place and set my career going on a twenty year journey to this book.
Read more about Alex Blewitt