8.4 Creating a LoadTest

8.4.1 Problem

You need to make sure that code executes correctly under varying load conditions, such as a large number of concurrent users.

8.4.2 Solution

Decorate an existing JUnit Test with a JUnitPerf LoadTest.

8.4.3 Discussion

A JUnitPerf LoadTest decorates an existing JUnit test to simulate a given number of concurrent users, in which each user may execute the test one or more times. By default, each simulated user executes the test once. For more flexibility, a load test may use a com.clarkware.junitperf.Timer to ramp up the number of concurrent users during test execution. JUnitPerf provides a ConstantTimer and RandomTimer to simulate delays between user requests. By default all threads are started at the same time by constructing a ConstantTimer with a delay of zero milliseconds.

If you need to simulate unique user information, each test must randomly choose a different user ID (for example). This can be accomplished using JUnit's setUp( ) method.

Here is an example that constructs a LoadTest with 100 simultaneous users:

public static Test suite(  ) {
    Test testCase = new TestSearchModel("testAsynchronousSearch");
    Test loadTest = new LoadTest(testCase, 100);
    TestSuite suite = new TestSuite(  );
    suite.addTest(loadTest);
    return suite;
}

Here is an example that constructs a LoadTest with 100 simultaneous users, in which each user executes the test 10 times:

public static Test suite(  ) {
    Test testCase = new TestSearchModel("testAsynchronousSearch");
    Test loadTest = new LoadTest(testCase, 100, 10);
    TestSuite suite = new TestSuite(  );
    suite.addTest(loadTest);
    return suite;
}

And here is an example that constructs a LoadTest with 100 users, in which each user executes the test 10 times, and each user starts at a random interval:

public static Test suite(  ) {
    Test testCase = new TestSearchModel("testAsynchronousSearch");
    Timer timer = new RandomTimer(1000, 500);
    Test loadTest = new LoadTest(testCase, 100, 10, timer);
    TestSuite suite = new TestSuite(  );
    suite.addTest(loadTest);
    return suite;
}

The Timer interface defines a single method, getDelay( ), that returns the time in milliseconds-to-wait until the next thread starts executing. The example above constructs a RandomTimer with a delay of 1,000 milliseconds (1 second), with a variation of 500 milliseconds (half a second). This means that a new user is added every one to one and a half seconds.

Be careful when creating timers that wait long periods of time between starting new threads. The longer the wait period, the longer it takes for the test to complete, which may or may not be desirable. If you need to test this type of behavior, you may want to set up a suite of tests that run automatically (perhaps at night).

There are commercial tools available for this type of performance test, but typically they are hard to use. JUnitPerf is simple and elegant, and any developer that knows how to write a JUnit test can sit down and write complex performance tests.

Example 8-2 shows how to create a JUnitPerf load test. As in the previous recipe, the use of the public static Test suite( ) method proves invaluable for integrating JUnitPerf tests into an Ant buildfile. More details on Ant integration are coming up in Recipe 8.6.

Example 8-2. JUnitPerf LoadTest
package com.oreilly.javaxp.junitperf;

import junit.framework.Test;
import junit.framework.TestSuite;
import com.clarkware.junitperf.TimedTest;

public class TestPerfSearchModel {

    public static Test suite(  ) {
        Test testCase = new TestSearchModel("testAsynchronousSearch");
        Test loadTest = new LoadTest(testCase, 
                                     100, 
                                     new RandomTimer(1000, 500));
        TestSuite suite = new TestSuite(  );
        suite.addTest(loadTest);
        return suite;
    }

    public static void main(String args[]) {
        junit.textui.TestRunner.run(suite(  ));
    }
}

8.4.4 See Also

Recipe 8.3 shows how to create a JUnitPerf TimedTest. Recipe 8.7 shows how to use Ant to execute JUnitPerf tests.