介绍
我们需要快速构建管道。这是因为我们需要从管道中快速反馈才能提高生产力。如果我们的代码出现问题,那么我们希望管道快速失败。为此,您可以决定允许项目中的测试并行测试执行。这篇文章描述了如何使用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为您提供并行运行测试的两种方法:
- 通过启动多个JVM实例
- 通过在同一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.xml
的build->pluginManagement->plugins
部分中的新插件。我们在撰写本文时导入了Surefire插件的最新版本。您可以检查this url以获取较新版本。
现在,当我们加载了Surefire插件的较新版本时,我们可以继续配置Maven以进行多线程测试执行。
在官方的Maven文档中,要实现这一目标,您需要使用parallel, threadCount
和useUnlimitedThreads
参数。我尝试了所有这些参数,但是没有与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
之后尝试运行测试,那么您会惊讶地发现测试仍在顺序运行。原因是您有两种策略可以在测试中允许并行执行。
- junit可以假设所有测试都是顺序的,只有用
@Execution(CONCURRENT)
注释的测试将并行执行。您可以在类或测试方法上使用此注释来启用并行执行。 - 您可以设置参数
junit.jupiter.execution.parallel.mode.default = concurrent
。在这里,默认情况下,所有测试都将并行运行,除了用ExecutionMode.SAME_THREAD
注释的测试。
Junit将使用多少个线程进行并行执行?
这也是可配置的属性junit.jupiter.execution.parallel.config.strategy=dynamic
,它还具有默认值dynamic
。策略也可以是fixed
或custom
。如果我们为该属性设置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。他们很难调试和识别。
如果您喜欢这篇文章,可以在Twitter或LinkedIn上关注我以获取更多内容。