Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parallelize test execution in a @Rule

I want to reuse some integration tests for load testing purposes. I implemented a rule which is parameterized by an annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Parallel {

    int invocations() default 1;

    int rampUpTime() default 0;
}

In my rule implementation the annotation is evaluated and a statement is set up, which has a evaluate method like that:

@Override
public void evaluate() throws Throwable {
    ScheduledExecutorService exe = Executors.newScheduledThreadPool(invocations);

    for (int i = 0; i < invocations; i++) {
        ScheduledFuture<?> scheduledFuture = exe.schedule(new Runnable() {

            @Override
            public void run() {
                try {
                    invocated++;

                    // Request test = Request.method(description.getTestClass(), description.getMethodName());
                    // new JUnitCore().run(test);

                    statement.evaluate();
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }, i * rampUpTime, this.timeUnit);
        futures.add(scheduledFuture);
    }
}

So, the evaluate call gets wrapped in a Runnable() and scheduled as described in the annotation. The thing is: In my rule, only the scheduling takes place, the runner doesn´t know (or care) about all the runables which only run as long as it takes to set up the whole test suite. So I´m trying to add the calls to evalute() to the test runner. First try was to use JUnitCore.run(...) which of course ends in a recursion.

Next try was to collect all the futures and wait for them to finish. This works fine on a per test basis, but I want to execute a whole test suite in parallel. And also, in my test report, I only see the test being executed once.

So then I thought I use a parameterized suite with a context (an object which collects all the futures from all tests) as parameter, but I didn´t found a way to promote this context object to the tests, each test has to have its own parameters.

I´m now asking for a way to add multiple executions from my rule to the test runner which is executing it.

like image 977
Alexander Hansen Avatar asked Dec 09 '13 14:12

Alexander Hansen


People also ask

Does TestNG run tests in parallel?

TestNG allows the tests to run in parallel or concurrent mode. This means that based on the test suite configuration, different threads are started simultaneously and the test methods are executed in them.

How do you run parallely tests in different browsers?

With Parallel Testing, you can run the same test on different browser/device combinations i.e. cross-browser testing, or run different tests on the same or different browser/device combinations. Parallel Testing will help you reduce the run time of your test suite, resulting in faster build times and faster releases.


1 Answers

If I'm understanding you correctly, you are trying to control the execution behaviour of the test runner. A TestRule might be to limited to achieve that goal. But how about writing your own Runner which controls the execution flow of your unit test? Just have a look at the ParentRunner of JUnit. From there, you should get a pretty good idea how the basic scheduling works, and maybe implement your own version of org.junit.experimental.ParallelComputer.

like image 52
Jim Holden Avatar answered Sep 23 '22 21:09

Jim Holden