JUNIT Integration

JUnit Integration

Integration with JUnit lets you test your AJAX code almost as easily as any other Java code.

Contents

  • Overview
    Integration with JUnit lets you test your AJAX code almost as easily as any other Java code.
  • Asynchronous Testing
    How to test event-driven features such as server calls or timers.
  • Benchmarking
    How to use GWT's JUnit support to create and report on benchmarks to help you optimize your code.

Overview

GWT includes a special GWTTestCase base class that provides JUnit integration. Running a compiled GWTTestCase subclass under JUnit launches an invisible GWT browser.

By default, tests run in hosted mode as normal Java bytecode in a JVM. Overriding this default behavior requires passing arguments to the GWT shell. Arguments cannot be passed directly through the command line, because normal command-line arguments go directly to the JUnit runner. Instead, define the system property gwt.args to pass arguments to GWT. For example, to run in web mode, declare -Dgwt.args="-web" as a JVM argument when invoking JUnit. To get a full list of supported options, declare -Dgwt.args="-help" (instead of running the test, help is printed to the console).

Creating a Test Case

GWT includes a handy junitCreator tool that will generate a starter test case for you, plus scripts for testing in both hosted mode and web mode. But here are the steps if you want to set it up by hand:

  1. Define a class that extends GWTTestCase.
  2. Create a module that causes the source for your test case to be included. If you are adding a test case to an existing GWT app, you can usually just use the existing module.
  3. Implement the method GWTTestCase.getModuleName() to return the fully-qualified name of the module.
  4. Compile your test case class to bytecode (using javac or a Java IDE).
  5. When running the test case, make sure your classpath includes:
    • your project's src directory
    • your project's bin directory
    • gwt-user.jar
    • gwt-dev-windows.jar (or gwt-dev-linux.jar)
    • junit.jar

Example

Write the com.example.foo.client.FooTest test case.
public class FooTest extends GWTTestCase {

/*
* Specifies a module to use when running this test case. The returned
* module must cause the source for this class to be included.
*
* @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
*/
public String getModuleName() {
return "com.example.foo.Foo";
}

public void testStuff() {
assertTrue(2 + 2 == 4);
}
}
Create the com.example.foo.Foo module.































Tip
You don't need to create a separate module for every test case. In the example above, any test cases in com.example.foo.client (or any subpackage) can share the com.example.foo.Foo module.

Asynchronous Testing

GWT's JUnit integration provides special support for testing functionality that cannot execute in straight-line code. For example, you might want to make an RPC call to a server and then validate the response. However, in a normal JUnit test run, the test stops as soon as the test method returns control to the caller, and GWT does not support multiple threads or blocking. To support this use case, GWTTestCase has extended the TestCase API.

The two key methods are GWTTestCase.delayTestFinish(int) and GWTTestCase.finishTest(). Calling delayTestFinish() during a test method's execution puts that test in asynchronous mode, which means the test will not finish when the test method returns control to the caller. Instead, a delay period begins, which lasts the amount of time specified in the call to delayTestFinish(). During the delay period, the test system will wait for one of three things to happen:

  1. If finishTest() is called before the delay period expires, the test will succeed.
  2. If any exception escapes from an event handler during the delay period, the test will error with the thrown exception.
  3. If the delay period expires and neither of the above has happened, the test will error with a TimeoutException.

The normal use pattern is to setup an event in the test method and call delayTestFinish() with a timeout significantly longer than the event is expected to take. The event handler validates the event and then calls finishTest().

Example

public void testTimer() {
// Setup an asynchronous event handler.
Timer timer = new Timer() {
public void run() {
// do some validation logic

// tell the test system the test is now done
finishTest();
}
};

// Set a delay period significantly longer than the
// event is expected to take.
delayTestFinish(500);

// Schedule the event and return control to the test system.
timer.schedule(100);
}
Tip
The recommended pattern is to test one asynchronous event per test method. If you need to test multiple events in the same method, here are a couple of techniques: "Chain" the events together. Trigger the first event during the test method's execution; when that event fires, call delayTestFinish() again with a new timeout and trigger the next event. When the last event fires, call finishTest() as normal. Set a counter containing the number of events to wait for. As each event comes in, decrement the counter. Call finishTest() when the counter reaches 0.

Benchmarking

GWT's JUnit integration provides special support for creating and reporting on benchmarks. Specifically, GWT has introduced a new Benchmark class which provides built-in facilities for common benchmarking needs. To take advantage of benchmarking support, take the following steps:
  1. Review the documentation on Benchmark. Take a look at the example benchmark code.
  2. Create your own benchmark by subclassing Benchmark. Execute your benchmark like you would any normal JUnit test. By default, the test results are written to a report XML file in your working directory.
  3. Run benchmarkViewer to browse visualizations (graphs/charts) of your report data. The benchmarkViewer is a GWT tool in the root of your GWT installation directory that displays benchmark reports.

0 comments: