使用Maven设置Junit 5并行测试执行
#java #testdev #junit #optimization

介绍

我们需要快速构建管道。这是因为我们需要从管道中快速反馈才能提高生产力。如果我们的代码出现问题,那么我们希望管道快速失败。为此,您可以决定允许项目中的测试并行测试执行。这篇文章描述了如何使用Maven和Junit 5。

Junit 5和Maven入门

要开始使用Junit 5,您需要将以下依赖性导入项目:


<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.0</version>
    <scope>test</scope>
</dependency>

在撰写本文时,版本 5.9.0 是最新的。您应该检查maven repository以获取新版本。请注意,我们在 test 范围中导入了库,因为该库不需要在生产代码中,因为我们仅将其用于运行测试。

并行运行测试

Maven为您提供并行运行测试的两种方法:

  1. 通过启动多个JVM实例
  2. 通过在同一JVM实例中使用多个线程

1.使用并行参数

并行测试执行的设置很简单。包括以下参数:

<forkCount>2</forkCount>

它必须具有大于1的值才能启用并行执行。重要的是要知道通过启动多个JVM子进程实现并行执行。这会产生多种后果,它可能会影响您使用此方法的决定。 Maven启动了多个JVM实例,这意味着它消耗了更多的内存。每个线程都有自己的内存空间。但是,由于流程无法共享数据,因此可以实现更高的测试独立性。当您需要使用内存数据库进行单元测试时,您可以使用此方法。

参数forkCount具有固定的正整数值,代表叉数。当然,通常,多个开发人员在同一项目上工作,我们不知道其他开发人员在其机器上会有多少核心。为了更好地使用硬件,如果我们可以设置此参数来创建许多取决于CPU上内核数的叉子,那将是很棒的。 Maven支持这一点,您可以通过以下方式进行配置:

<forkCount>1C</forkCount>

此配置指示Maven为每个核心创建一个叉子。如果您的CPU每个核心有两个虚拟线程,则还可以输入2C使用大多数CPU资源。或者,如果您不想使用CPU的100%,则可以输入0.5C,该0.5C将指示Maven为CPU内核的一半创建叉子。

2.通过设置JUNIT多线程执行

Maven将插件用于所有内容。运行项目测试也是如此。为了运行项目测试,Maven使用SureFire插件。不幸的是,默认情况下,它使用插件的旧版本,该版本不支持Junit5测试执行。因此,我们需要将此插件的较新版本导入Maven。要包含此插件的较新版本,我们需要配置Maven。我们可以通过将以下XML添加到pom.xml
来做到这一点


<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M7</version>
                <configuration>
                    We will add configuration here
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

XML具有自我描述性。我们添加了Maven pom.xmlbuild->pluginManagement->plugins部分中的新插件。我们在撰写本文时导入了Surefire插件的最新版本。您可以检查this url以获取较新版本。

现在,当我们加载了Surefire插件的较新版本时,我们可以继续配置Maven以进行多线程测试执行。

在官方的Maven文档中,要实现这一目标,您需要使用parallel, threadCountuseUnlimitedThreads参数。我尝试了所有这些参数,但是没有与Junit 5一起使用。因此,要配置多线程执行,我们也需要配置Junit5。我们可以通过在Maven配置中设置属性来做到这一点。


<configuration>
    <properties>
        <configurationParameters>
            junit.jupiter.execution.parallel.enabled=true
            ...
        </configurationParameters>
    </properties>
</configuration>

另一个选项是创建junit-platform.properties文件。将其放入test/resources文件夹中,然后将所有属性放在该文件中而不是pom.xml中。

足以设置junit.jupiter.execution.parallel.enabled=true以允许并行测试执行。但是,如果您在将此参数值设置为true之后尝试运行测试,那么您会惊讶地发现测试仍在顺序运行。原因是您有两种策略可以在测试中允许并行执行。

  1. junit可以假设所有测试都是顺序的,只有用@Execution(CONCURRENT)注释的测试将并行执行。您可以在类或测试方法上使用此注释来启用并行执行。
  2. 您可以设置参数junit.jupiter.execution.parallel.mode.default = concurrent。在这里,默认情况下,所有测试都将并行运行,除了用ExecutionMode.SAME_THREAD注释的测试。

Junit将使用多少个线程进行并行执行?

这也是可配置的属性junit.jupiter.execution.parallel.config.strategy=dynamic,它还具有默认值dynamic。策略也可以是fixedcustom。如果我们为该属性设置fixed值,那么我们还需要设置junit.jupiter.execution.parallel.config.fixed.parallelism=<positive integer>的值。这不是可扩展的解决方案,我们应该使用dynamic值来更好地利用硬件。

dynamic属性还具有连接的属性,该属性会影响junit将创建多少线程。 junit.jupiter.execution.parallel.config.dynamic.factor=<positive decimal number>。乘以处理器/内核的数量,以确定动态配置策略的所需并行性。

结论

并行测试执行可以加快构建速度,但是在启用它时必须小心,因为它不会总是为您提供更好的性能。这是因为测试可能会使用相同的资源,他们可以互相等待访问它。因此,测试和检查所有内容总是一个好主意。

并行测试的另一个更重要的问题是,如果测试不是独立的,则可能会有flaky tests。他们很难调试和识别。

如果您喜欢这篇文章,可以在TwitterLinkedIn上关注我以获取更多内容。

资源

Maven documentation

Junit guide

JUnit5 Parallel Execution of tests