在Maven构建中并行运行junit测试?

问题

我正在使用JUnit 4.4和Maven,并且我有大量长时间运行的集成测试。

在并行化测试套件时,有一些解决方案允许我在一个测试类中并行运行每个测试方法。但所有这些都要求我以某种方式改变测试。

我真的认为在X线程中并行运行X个不同的测试类会是一个更清晰的解决方案。我有数百个测试,所以我并不真正关心线程化各个测试类。

有没有办法做到这一点?


#1 热门回答(69 赞)

使用maven插件:

<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>

#2 热门回答(38 赞)

从junit 4.7开始,现在可以在不使用TestNG的情况下并行运行测试。实际上从4.6开始就有可能,但是在4.7中有一些修正,这将使它成为一个可行的选择。你也可以使用spring运行并行测试,你可以阅读abouthere


#3 热门回答(10 赞)

受JUnit试验ParallelComputerrunner的启发,我已经建立了自己的ParallelSuiteParallelParameterizedrunners。使用这些运行程序,可以轻松地并行化测试套件和参数化测试。
ParallelSuite.java

public class ParallelSuite extends Suite {

    public ParallelSuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {

        super(klass, builder);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(4);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

ParallelParameterized.java

public class ParallelParameterized extends Parameterized {

    public ParallelParameterized(Class<?> arg0) throws Throwable {

        super(arg0);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(8);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

用法很简单。只需将**@RunWith注解值更改为其中一个并行***classes。

@RunWith(ParallelSuite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {}