【问题标题】:Maven: Ignore inter-module dependencies while running unit testsMaven:运行单元测试时忽略模块间依赖关系
【发布时间】:2016-06-22 21:38:03
【问题描述】:

我们有一个大型的多模块 Maven 项目。我一直在尝试使用 -T 选项加速我们的单元测试构建,并取得了一些积极的结果。但是,我们的项目中有一些依赖路径是这样的:

模块 A

每个模块的单元测试需要 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 的单元测试需要大量工作,并且不能保证单个模块中的测试是可并行的

【问题讨论】:

    标签: maven unit-testing jenkins build multi-module


    【解决方案1】:

    可能的解决方案如下:

    • 创建一个附加模块,比如testsuite-module
    • 将所有其他模块作为test范围内的依赖项添加到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-module 对您的项目无害,如果需要(和推荐),您还可以将其移至 CI 配置文件,如 this SO post 中所述
    • 您也可以考虑使用 Build Helper 插件的 add-test-resource 目标
    • 您可能在测试名称(不同模块中具有相同名称的两个测试用例)或测试资源上存在冲突,这可能是一个更大的问题,但并非不可能解决
    • 如果依赖模块的测试首先失败,您可能会浪费时间(并且会适得其反),但您的需求已经预见到这一方面(我想是假设)

    【讨论】:

    • 这确实是一个不错的解决方案,没想到那个。 +1
    • 感谢您的解决方案——非常好!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 2019-12-14
    相关资源
    最近更新 更多