Unitils compositeTest Module

When automating complex testscenarios (like end-to-end tests), you may need to execute a combination of batches, webservice calls, web application interactions, etc, maybe even on different points in time. In unitils, we have support for all those components, but you could not orchestrate them easy. That is where the compositeTest module comes in.

Now you can define each step as if it was a standalone test : you can specify the time with unitils-jodatime, prepare the database via dbunit, call a batch/send a webservice message/do something in a webpage. In fact, any annotation based module that you use in a normal test also works for the testpart. And of course, you can do the necessary asserts for that part of your complicated scenario directly in the testpart.

In the end, you simply specify the sequence in which the parts are executed. This also makes it easy to reuse certain blocks to in multiple scenario's.

If you would like to get a report for a testpart, no problem : each step is in fact a standalone test, but not reported as such. In the default behaviour, you will only get a failed/passed for the test(s) that execute the parts. If you want a testpart to report its status as well in a standalone manner, you can specify this in the annotation.

CompositeTest Module load artifact (maven)

    <dependency>
        <groupId>org.unitils.compositetest</groupId>
        <artifactId>unitils-compositeTest</artifactId>
        <version>1.0.0</version>
    </dependency>

CompositeTest Module project config

unitils.modules=[...other modules...], compositetest, [...other modules...]

unitils.module.compositetest.className = org.unitils.compositetest.CompositeTestModule
unitils.module.compositetest.runAfter=
unitils.module.compositetest.enabled=true

CompositeTest Module example

public class MultiPartJUnit4Test_TestClass extends UnitilsJUnit4TestBase {


    @CompositeTestHandler
    private CompositeTestDriver mpTestDriver;


    @Test
    public void testMain() {
        ... do some tests.
        registerTestInvocation(TestInvocation.TEST_METHOD, this.getClass(), "main"); 
    }


    @Test
    @TestPart(name="part2")    
    public void testPart2() {
        ... do some tests.
        registerTestInvocation(TestInvocation.TEST_METHOD, this.getClass(), "part2"); 
    }

    @Test
    @TestPart(name="part3", executeAsSingleTest=true)    
    public void testPart3() {
        ... do some tests.
        registerTestInvocation(TestInvocation.TEST_METHOD, this.getClass(), "part3"); }

    @Test
    public void multi() {
        ... do some tests.

        this.mpTestDriver.launchTestPart("testPart1"); // via method name
        this.mpTestDriver.launchTestPart("part2");        
        this.mpTestDriver.launchTestPart("part3");
        registerTestInvocation(TestInvocation.TEST_METHOD, this.getClass(), "multi"); // has to be the last, otherwise the check on executed method freaks out.
    }

    @Test
    @TestPart
    public void testPart1() {
        ... do some tests.
        // behind the multi() method, order is not important
        registerTestInvocation(TestInvocation.TEST_METHOD, this.getClass(), "part1"); 
    }

}

In the previous example there are 5 tests, but only 3 tests are executed:

  • testPart3
  • testMain
  • multi

But the multi test executes testPart1, testPart2, testPart3 and the multi test itself.
There are 2 ways to execute a test:

  • @Test without @TestPart
  • @Test + @TestPart + executeAsSingleTest=true
 

Last edit: Willemijn Wouters 2014-02-04