Time for action – waiting for a condition

Typically, an action may require a result to happen in the user interface before testing can continue. Since SWTBot can run much faster than a human can, waiting for a 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 called createJavaProject() in the UITest class.
  2. Use the bot to create a new Java project by copying the createProject() method as a template.
  3. Add org.eclipse.core.resources as a dependency to the plug-in.
  4. Add a method getProject(), which returns an IProject from ResourcesPlugin.getWorkspace().getRoot().getProject().
  5. Use the getProject() with the test project to get the src folder .
  6. If the folder does not exist, create it.
  7. Get the file called Test.java from src.
  8. Create it with the contents from the "class {}".getBytes() bytes as a ByteArrayInputStream.
  9. Use the bot.waitUntil() call to pass in a new anonymous subclass of DefaultCondition.
  10. In the test() method of the condition, return if the project's bin folder has a file called Test.class.
  11. In the getFailureMessage() of the condition, return a suitable message.
  12. The code looks like the following snippet:
    @Test
    public void createJavaProject() throws Exception {
      String projectName = "SWTBot Java Project";
      bot.menu("File").menu("Project...").click();
      SWTBotShell shell = bot.shell("New Project");
      shell.activate();
      bot.tree().expandNode("Java").select("Java Project");
      bot.button("Next >").click();
      bot.textWithLabel("Project name:").setText(projectName);
      bot.button("Finish").click();
      final IProject project = getProject(projectName);
      assertTrue(project.exists());
      final IFolder src = project.getFolder("src");
      final IFolder bin = project.getFolder("bin");
      if (!src.exists()) {
        src.create(true, true, null);
      }
      IFile test = src.getFile("Test.java");
      test.create(new ByteArrayInputStream("class Test{}".getBytes()), true, null);
      bot.waitUntil(new DefaultCondition() {
        @Override
        public boolean test() throws Exception {
          return project.getFolder("bin").getFile("Test.class").exists();
          }
        public String getFailureMessage() {
          return "File bin/Test.class was not created";
        }
      });
      assertTrue(bin.getFile("Test.class").exists());
    }
  13. Run the test and verify that it was successful.
  14. Comment out the waitUntil() call and verify that the test fails.

What just happened?

When the Test.java file is created in the project, an event is fired that runs the Java compiler. This in turn results in the creation of both the bin folder, as well as the Test.class file that is being tested. However, both of these operations occur on different threads, and so while the test is running, if it needs to act on the generated file, it must wait until that file is created.

Although this example could have been implemented outside of SWTBot, it provides a simple way to block the execution until a particular condition occurs. This can be useful if the user interface is running some kind of long-running action and the code needs to wait until a certain dialog message is shown, or something that can be determined programmatically (such as the file's existence, as in this case).

Other types of conditionals and tests are possible as well; there is a waitWhile(), which is similar to the bot's waitUntil() but has the opposite behavior.

Note that when the wait condition is commented out, the test fails, because the test execution thread will hit the assertion before the Java compiler has been run.

One advantage of using the wait code in SWTBot is that if the condition doesn't occur within a given timeout then an exception is generated and the test will fail. Since the same wait condition is used elsewhere in SWTBot, the delay is configurable and can be changed externally.

Have a go hero – driving the New Class wizard

Instead of using the source file as a text file, use SWTBot to open the New Class wizard by going to the File menu. Pass in the name of the project, the package, and the class; the source and class files should be created in the background. This is how integration tests (that show the application working from a user's perspective) can be implemented, instead of having a set of tests that show only the underlying libraries at work.

Pop quiz – understanding SWTBot

Q1. What is the name of the JUnit test runner that is required for SWTBot?

Q2. How are views shown with SWTBot?

Q3. How do you get the text value of a field in a dialog?

Q4. What is a Matcher and when is it to be used?

Q5. How can values from the UI be returned to the user without having to worry about thread interaction?

Q6. When some asynchronous events are happening in the background, how can the test wait (without blocking the test) until a particular condition occurs?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset