Maven:在 运行 单元测试时忽略模块间依赖关系
Maven: Ignore inter-module dependencies while running unit tests
我们有一个大型的多模块 Maven 项目。我一直在尝试使用 -T 选项加速我们的单元测试构建,并取得了一些积极的结果。然而,在我们的项目中有一些依赖路径是这样的:
模块 A <- 模块 B <- 模块 C
每个模块的单元测试需要 20-30 分钟。由于 -T 选项按依赖顺序构建模块,因此总构建时间为 90 分钟。如果我可以先编译所有模块,然后 运行 并行测试 A、B 和 C,那将真正加快构建速度。例如。像这样:
$ mvn -T 10 clean install -DskipTests
$ mvn -T 10 --ignore-dependencies test
问题:Maven 是否支持开箱即用?
我一直在考虑编写一个小脚本来解析 mvn dependency:tree 的输出并并行调用 "mvn test -pl A"、"mvn test -pl B" 等等,但是显然,如果 Maven 有一个开箱即用的解决方案,那就更好了。
我们正在使用 Jenkins,所以如果有一些 Jenkins 插件或我错过的 Jenkins 功能支持这个,那可能会有很大帮助!
注意:加速 A、B 和 C 的单元测试将需要大量工作,并且不能保证单个模块中的测试是可并行的
可能的解决方案如下:
- 创建一个附加模块,比如
testsuite-module
- 将所有其他模块作为
test
范围内的依赖项添加到 testsuite-module
- 通过Build Helper Maven Plugin and its
add-test-source
目标 将其他模块的所有测试源添加到testsuite-module
- 仅在此模块上执行作业的第二步并运行 并行测试
例如,testsuite-module
的 POM 文件可能如下所示:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sample</groupId>
<artifactId>modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>testsuite-module</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../module-a/src/test</source>
<source>../module-b/src/test</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.sample</groupId>
<artifactId>module-a</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sample</groupId>
<artifactId>module-b</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
它的唯一范围是收集其他模块的所有源代码测试,在测试中包含所需的模块 scope/classpath 并通过例如:
执行它们
mvn -pl testsuite-module test -T 10
这将在一次测试执行中执行所有测试,因此可能满足您的要求。
关于这种方法的一些注意事项:
testsuite-module
对您的项目无害,如果需要(和推荐),您也可以将其移至 CI 配置文件,如 this SO post[=43 中所述=]
- 您也可以考虑使用 Build Helper 插件的
add-test-resource
目标
- 您可能在测试名称(不同模块中具有相同名称的两个测试用例)或测试资源上有冲突,这可能是一个更大的问题,但不应该无法解决
- 如果来自依赖模块的测试首先失败,您可能会浪费时间(并且会适得其反),但是您的需求已经预见到这一方面(我想是假设)
我们有一个大型的多模块 Maven 项目。我一直在尝试使用 -T 选项加速我们的单元测试构建,并取得了一些积极的结果。然而,在我们的项目中有一些依赖路径是这样的:
模块 A <- 模块 B <- 模块 C
每个模块的单元测试需要 20-30 分钟。由于 -T 选项按依赖顺序构建模块,因此总构建时间为 90 分钟。如果我可以先编译所有模块,然后 运行 并行测试 A、B 和 C,那将真正加快构建速度。例如。像这样:
$ mvn -T 10 clean install -DskipTests
$ mvn -T 10 --ignore-dependencies test
问题:Maven 是否支持开箱即用?
我一直在考虑编写一个小脚本来解析 mvn dependency:tree 的输出并并行调用 "mvn test -pl A"、"mvn test -pl B" 等等,但是显然,如果 Maven 有一个开箱即用的解决方案,那就更好了。
我们正在使用 Jenkins,所以如果有一些 Jenkins 插件或我错过的 Jenkins 功能支持这个,那可能会有很大帮助!
注意:加速 A、B 和 C 的单元测试将需要大量工作,并且不能保证单个模块中的测试是可并行的
可能的解决方案如下:
- 创建一个附加模块,比如
testsuite-module
- 将所有其他模块作为
test
范围内的依赖项添加到testsuite-module
- 通过Build Helper Maven Plugin and its
add-test-source
目标 将其他模块的所有测试源添加到 - 仅在此模块上执行作业的第二步并运行 并行测试
testsuite-module
例如,testsuite-module
的 POM 文件可能如下所示:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sample</groupId>
<artifactId>modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>testsuite-module</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../module-a/src/test</source>
<source>../module-b/src/test</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.sample</groupId>
<artifactId>module-a</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sample</groupId>
<artifactId>module-b</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
它的唯一范围是收集其他模块的所有源代码测试,在测试中包含所需的模块 scope/classpath 并通过例如:
执行它们mvn -pl testsuite-module test -T 10
这将在一次测试执行中执行所有测试,因此可能满足您的要求。
关于这种方法的一些注意事项:
testsuite-module
对您的项目无害,如果需要(和推荐),您也可以将其移至 CI 配置文件,如 this SO post[=43 中所述=]- 您也可以考虑使用 Build Helper 插件的
add-test-resource
目标 - 您可能在测试名称(不同模块中具有相同名称的两个测试用例)或测试资源上有冲突,这可能是一个更大的问题,但不应该无法解决
- 如果来自依赖模块的测试首先失败,您可能会浪费时间(并且会适得其反),但是您的需求已经预见到这一方面(我想是假设)