在 Maven 版本中并行运行 junit 测试?

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

当涉及到并行化测试套件时,有一些解决方案允许我在单个测试类中并行运行每个测试方法。但是所有这些都要求我以这样或那样的方式改变测试。

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

有什么办法吗?

87444 次浏览

TestNG 可以做到这一点 (这是我的第一个反射——然后我看到您已经有了很多测试用例)。

对于 JUnit,请查看 平行连接器

您可以在一分钟内将您的测试更改为 TestNg 测试(您只需更改导入) ,TestNG 是最好的并行测试。

You could try 格瑞吉 that lets you run distribute your tests across a compute grid.

From junit 4.7 it's now possible to run tests in parallel without using TestNG. Actually it has been possible since 4.6, but there are a number of fixes being made in 4.7 that will make it a viable option. You may also run parallel tests with spring, which you can read about 给你

Temus-fugit 提供了类似的东西,查看文档了解详细信息。它依赖于 JUnit 4.7,您只需将测试标记为 @RunWith(ConcurrentTestRunner)

干杯

您可以查看开放源码库 -测试负载均衡器。它完全满足您的要求——并行运行不同的测试类。这在 ant-junit 级别进行了集成,因此您无论如何都不必更改您的测试。我是图书馆的作者之一。

Also, think about not running them in threads as you may need a process level sandbox. For example, if you are hitting a DB in your integration tests, you do not want one test to fail because another test added some data in a different thread. Most of the times, tests are not written with this in mind.

Finally, how have solved this problem till now?

使用专家插件:

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

受 JUnit 的实验性 并行计算机(ParallelComputer.java)运行器的启发,我已经建立了自己的 ParallelSuite并行参数化运行器。使用这些运行程序可以轻松地并行化测试套件和参数化测试。

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);
}
}
});
}
}

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注释值更改为这些 平行 * 类中的一个。

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

您可以使用 Junit 本身提供的 ParallelComputer 并行运行测试。这里有一个小片段可以让你开始。

Class[] cls = { TestCase1.class, TestCase2.class };
Result result = JUnitCore.runClasses(ParallelComputer.classes(), cls);
List<Failure> failures = result.getFailures();

当需要从代码运行测试时,这将有所帮助,因为它不依赖于 Maven 或任何其他构建管理工具。

请注意,这将并行运行所有测试用例,如果您在不同的测试用例之间有任何依赖关系,它可能会导致误报。无论如何,你不应该有相互依赖的测试。

Another choice: Punner, a new parallel junit runner and maven plugin. You don't have to change your code, copy it to your pom.xml:

<!-- Disable default surefire based testing -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>


<plugin>
<groupId>com.github.marks-yag</groupId>
<artifactId>punner-maven-plugin</artifactId>
<version>${version}</version>
<configuration>
</configuration>
<executions>
<execution>
<id>test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>

剪板机可以并行运行测试方法,可以保持测试输出分开和清洁。

Punner 将减少 mvn 控制台的输出,如下所示:

[INFO] --- punner-maven-plugin:0.9.13:test (test) @ ipc ---
[INFO] Punner report directory: /Users/guile/workspace/ipc/target/punner-reports
[INFO]
[INFO] com.github.yag.ipc.IPCTest.testConnectionHandler.............. PASSED
[INFO] com.github.yag.ipc.IPCTest.testSequence....................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testPartialContent................. PASSED
[INFO] com.github.yag.ipc.IPCTest.testResponseContent................ PASSED
[INFO] com.github.yag.ipc.IPCTest.testPingPong....................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testServerClose.................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testServerSideHeartbeatTimeout..... PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientSideHeartbeatTimeout..... PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientSideHeartbeat............ PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientReconnect................ PASSED
[INFO]
[INFO] Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.952 sec, Time saved: 25.919 sec.

Punner 产生的兼容输出,您还可以从报告目录获得原始日志数据和降价格式报告:

➜  ipc git:(develop) ll target/punner-reports
total 104
-rw-r--r--   1 guile  staff    11K Oct 15 23:07 TEST-com.github.yag.ipc.IPCTest.xml
-rw-r--r--   1 guile  staff   298B Oct 15 23:07 com.github.yag.ipc.IPCTest.txt
drwxr-xr-x  12 guile  staff   384B Oct  8 00:50 logs
-rw-r--r--   1 guile  staff    33K Oct 15 23:07 report.md

Punner 是我个人的一个项目,我写 Punner 是为了加快其他一些项目的单元测试阶段,如 IPC 框架、细粒度锁定、日志服务、分布式工作流引擎等。节省了我很多等待的时间。

Punner don't support some advanced feature yet. I'm very glad if you could try it and give me some feedback.