114

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

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

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

有没有办法做到这一点?

4

10 回答 10

80

使用 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>
于 2012-02-29T11:31:18.833 回答
42

从 junit 4.7 开始,现在可以在不使用 TestNG 的情况下并行运行测试。实际上,从 4.6 开始就可以了,但是在 4.7 中进行了许多修复,这将使其成为一个可行的选择。你也可以使用 spring 运行并行测试,你可以在这里阅读

于 2009-07-08T14:31:26.817 回答
10

受 JUnit 的实验性ParallelComputer跑步者的启发,我构建了自己的ParallelSuiteParallelParameterized跑步者。使用这些运行器可以轻松地并行化测试套件和参数化测试。

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注释值更改为这些Parallel*类之一。

@RunWith(ParallelSuite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {}
于 2013-05-25T14:46:57.173 回答
5

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

干杯

于 2010-01-02T12:22:57.937 回答
3

您可以查看开源库 - Test Load Balancer。它完全符合您的要求 - 并行运行不同的测试类。这在 ant-junit 级别集成,因此您无需更改测试。我是图书馆的作者之一。

此外,请考虑不要在线程中运行它们,因为您可能需要进程级沙箱。例如,如果您在集成测试中遇到数据库,您不希望一个测试失败,因为另一个测试在不同的线程中添加了一些数据。大多数时候,编写测试时并没有考虑到这一点。

最后,到目前为止,这个问题是如何解决的?

于 2011-06-04T05:26:45.813 回答
2

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

对于 JUnit,请查看parallel-junit

于 2009-01-08T11:01:05.177 回答
2

您可以使用 Junit 本身提供的 ParallelComputer 并行运行测试。这是一个小片段,可以帮助您入门。

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

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

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

于 2013-12-26T11:30:31.673 回答
0

另一个选择:Punner,一个新的并行 junit runner 和 maven 插件。您不必更改代码,将其复制到您的 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 可以并行运行测试方法,可以单独保持测试输出和清洁。

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 还不支持某些高级功能。如果你能尝试一下并给我一些反馈,我很高兴。

于 2019-10-15T15:33:58.567 回答
-3

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

于 2009-01-08T16:34:22.787 回答
-3

您可以尝试使用 Gridgain,它可以让您在计算网格中运行分布测试。

于 2009-04-08T08:23:56.780 回答