Maven:在运行单元测试时忽略模块间依赖关系

我们有一个大型的多模块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依赖的输出:树并调用“mvn test -pl A”,“mvn test -pl B”等并行,但很明显如果是Maven有一个开箱即用的解决方案,这是更好的选择.

我们正在使用Jenkins,所以如果有一些Jenkins插件或Jenkins的功能,我错过了支持这个,这可能会有很大帮助!

注意:加快A,B和C的单元测试将需要大量的工作,并且无法保证单个模块中的测试可并行化

最佳答案 可能的解决方案如下:

>创建一个额外的模块,比如testsuite-module
>将testsuite-module中的所有其他模块添加为测试范围中的依赖项
>通过Build Helper Maven Plugin及其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>

它唯一的范围是收集其他模块的所有源测试,在测试范围/类路径中具有所需的模块并通过例如执行它们:

mvn -pl testsuite-module test -T 10

这将在单个测试执行中执行所有测试,因此可能满足您的要求.

关于这种方法的几点考虑:

>如果需要(并推荐),testsuite模块对您的项目将是无害的,您也可以将其移动到CI配置文件,如this SO post中所述
>您可以考虑使用Build Helper插件的add-test-resource目标
>您可能在测试名称(两个在不同模块中具有相同名称的测试用例)或测试资源上存在冲突,但这可能是一个问题,但不应该无法解决它
>如果来自相关模块的测试首先失败,您可能会浪费时间(并且会适得其反),但是这个方面已经被您的要求所预见(假设,我想)

点赞