19

I would like to run every method annotated with @Test, across multiple classes, at the same time. For some cases, I would like to limit this, and say that only 100 total can run at any one time. I would like methods with @BeforeClass annotations to be run once before any Test in a class runs, and I would like @AfterClass annotations to be run once after all Tests in a class run. I would like System.out, System.err, and Exceptions to be appropriately buffered/captured rather than written out, so that they don't interleave, and I can read the final output and understand what happened.

Does this exist? I have a large number of independent test cases, and my application is (I believe) threadsafe. None of these tests have dependencies out of the JVM, and I want to finish them as quickly as possible, given my hardware.

If this doesn't exist, is there a concrete reason why not? How much time is lost by junit users worldwide because this isn't easy? Can I build it into Junit? In my mind, this should be as simple as a single flag, and it "just works".

Cory Kendall
  • 7,195
  • 8
  • 37
  • 64

3 Answers3

22

You can accomplish this with JUnit's ParallelComputer (note it's still considered experimental). It's a pretty simple implementation which is backed by the java.util.concurrent.ExecutorService API.
If you're curious how it works, check out the source.

Basically you call JUnitCore.runClasses(Computer, Classes ...) and pass in a ParallelComputer object for the first argument.

Example usage:

import org.junit.Test;
import org.junit.experimental.ParallelComputer;
import org.junit.runner.JUnitCore;

public class ParallelComputerExample {

    @Test
    public void runAllTests() {
        Class<?>[] classes = { ParallelTest1.class, ParallelTest2.class };

        // ParallelComputer(true,true) will run all classes and methods 
        // in parallel.  (First arg for classes, second arg for methods)
        JUnitCore.runClasses(new ParallelComputer(true, true), classes);
    }

    public static class ParallelTest1 {
        @Test
        public void test1a() {
            lookBusy(3000);
        }

        @Test
        public void test1b() {
            lookBusy(3000);
        }
    }

    public static class ParallelTest2 {
        @Test
        public void test2a() {
            lookBusy(3000);
        }

        @Test
        public void test2b() {
            lookBusy(3000);
        }
    }

    public static void lookBusy(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }
    }
}

The above code will run in 3 seconds because all methods and classes are ran in parallel.

This will run in 6s (because all classes are in parallel). JUnitCore.runClasses(new ParallelComputer(true, false), classes);

This will also run in 6s (because all methods are in parallel). JUnitCore.runClasses(new ParallelComputer(false, true), classes);

palacsint
  • 28,416
  • 10
  • 82
  • 109
Andy Guibert
  • 41,446
  • 8
  • 38
  • 61
  • 10
    You should not call JUnitCore.runClasses() from a @Test. This will mess up the test reports. See: https://github.com/junit-team/junit4/issues/1102 The real solution to run test in parallel is to extend the Runner or the Suite – Luigi Massa Gallerano Mar 20 '17 at 17:47
  • https://examples.javacodegeeks.com/core-java/junit/junit-run-tests-in-parallel/ – Cristian Florescu Jul 07 '18 at 21:15
9

Yes, You can.

If you are using maven. You can take help of

maven-surefire-plugin

In Spring,

You can check this Link

<build>
    <plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.7.1</version>
        <configuration>
            <parallel>classes</parallel>
            <threadCount>5</threadCount>
        </configuration>
    </plugin>
    </plugins>
</build>

Solution 2: Junit4 provides parallel feature using ParallelComputer

VedantK
  • 9,728
  • 7
  • 66
  • 71
  • 1
    How do I make sure tests are running in parallel? I don't see any reduction in execution time of test cases – Arun Gowda Nov 05 '19 at 05:09
5

JUnit Toolbox provides JUnit runners for parallel execution of tests.

In order to not intermix output to System.err and System.out you have to start tests in separate JVMs, because System.err and System.out are global.

Stefan Birkner
  • 24,059
  • 12
  • 57
  • 72
  • 1
    This IntelliJ plugin is built on top of JUnit Toolbox: https://plugins.jetbrains.com/plugin/12959-junit4-parallel-runner. – Csa77 Sep 15 '20 at 18:21