66

我在同一个文件夹(src/test/java)中有一个包含集成和单元测试的多模块 maven 项目。集成测试用 标记@Category(IntegrationTest.class)。我想结束以下设置:

  1. 如果我运行mvn install,我希望编译所有测试,但我不想执行任何测试。
  2. 如果我运行mvn test,我希望编译所有测试,但只执行单元测试。
  3. 如果我运行mvn integration-test,我想编译并执行所有测试。

重要的一点是,我希望在pom.xml没有任何额外命令行参数的情况下对其进行配置。

目前我在我的父 pom.xml 中提出了以下设置,唯一的问题是 #1,所有测试都在其中执行:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${project.java.version}</source>
                    <target>${project.java.version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.14.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.14.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <includes>
                        <include>**/*.class</include>
                    </includes>
                    <excludedGroups>cz.cuni.xrg.intlib.commons.IntegrationTest</excludedGroups>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.14.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.14.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <groups>cz.cuni.xrg.intlib.commons.IntegrationTest</groups>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                        <configuration>
                            <includes>
                                <include>**/*.class</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

所有子模块的 pom.xml 中都有以下插件配置,我认为应该从父 pom 继承:

<build> 
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
        </plugin>

        <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
        </plugin>
    </plugins>
</build>

我尝试使用<skipTests>true</skipTests>,但它禁用了所有目标的测试执行,这不是我想要的(违反 #2 和 #3)。这也很奇怪,它mvn test尊重skipTests=true选项......我为什么要首先运行它?

经过数小时的谷歌搜索和尝试不同的组合,我犹豫是否可以不运行测试mvn install,同时运行它们mvn test。我希望有人证明这是错误的。;)

我也愿意接受一个mvn install只执行单元测试的解决方案,但我认为它没有太大区别。

4

7 回答 7

107

听起来您不了解Maven中构建生命周期的概念。如果您运行mvn install所有生命周期阶段(包括install阶段本身),请在安装阶段之前运行。这意味着运行以下阶段:

  1. 证实
  2. 初始化
  3. 生成源
  4. 过程源
  5. 生成资源
  6. 流程资源
  7. 编译
  8. 进程类
  9. 生成测试源
  10. 过程测试源
  11. 生成测试资源
  12. 过程测试资源
  13. 测试编译
  14. 过程测试类
  15. 测试
  16. 准备包
  17. 包裹
  18. 预集成测试
  19. 集成测试
  20. 整合后测试
  21. 核实
  22. 安装

换句话说,这意味着test包括生命周期阶段和integration-test生命周期阶段。因此,如果没有任何补充信息,就不可能按照您的意愿更改行为。

它可以通过在 Maven 中使用配置文件来实现:

 <project>
  [...]
  <profiles>
    <profile>
      <id>no-unit-tests</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
              <skipTests>true</skipTests>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
  [...]
</project>

所以你的第一个要求:

  1. 如果我运行mvn install,我希望编译所有测试,但我不想执行任何测试。

可以通过使用以下方法来实现:

mvn -Pno-unit-test test
  1. 如果我运行mvn test,我希望编译所有测试,但只执行单元测试。

这可以通过使用普通调用来简单地实现:

mvn test

导致集成测试阶段未运行(请参阅构建生命周期)。

  1. 如果我运行mvn integration-test,我想编译并执行所有测试。

这意味着运行默认设置,其中包括运行test将运行单元测试(maven-surefire-plugin)的阶段,并进一步运行由 maven-failsafe-plugin 处理的集成测试。但是您应该知道,如果您想调用集成测试,您应该使用以下命令:

mvn verify

相反,导致您错过了post-integration-test上一次通话中的阶段。

除了上述之外,您应该遵循单元测试和集成测试的命名约定,其中单元测试的命名应如下所示:

<includes>
 <include>**/*Test*.java</include>
 <include>**/*Test.java</include>
 <include>**/*TestCase.java</include>
</includes>

集成测试应命名如下:

<includes>
 <include>**/IT*.java</include>
 <include>**/*IT.java</include>
 <include>**/*ITCase.java</include>
</includes>

我希望你已经像下面这样配置了 maven-failsafe-plugin,这是将 maven-failsafe-plugin 绑定到正确的生命周期阶段所必需的:

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.15</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

正如您所做的那样,但您应该知道include标签适用于源代码(.java)而不是编译名称( .class)。我不会使用 Category 注释,只是简单地使用命名约定使 pom 更简单更短。

于 2013-06-15T13:04:14.743 回答
58

根据故障安全插件文档

mvn install -DskipITs

是你想要的。

于 2013-10-07T18:09:53.700 回答
21

OP在他的问题中所说的:

如果我运行mvn install,我希望编译所有测试,但我不想执行任何测试。
如果我运行mvn test,我希望编译所有测试,但只执行单元测试。
如果我运行mvn integration-test,我想编译并执行所有测试。

是完全有效的并且非常容易实现。
编辑:除了第一个条件,它违背了行家的本质。这里最好的方法就是简单地做mvn install -DskipTests

您只需要以下代码段pom.xml

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.17</version>
    <executions>
        <execution>
            <id>integration-tests</id>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>

并坚持单元和集成测试的maven 命名约定(正如@khmarbaise 已经说过的那样)。IT因此,通常使用后缀(例如)命名您的集成测试MyIntegrationTestIT.java并让它maven-failsafe完成它的工作。
这样,您甚至不需要 JUnit 类别(尽管有时它们可​​能非常有用)。

而已 :)

  • mvn test 执行单元测试
  • mvn integration-test 执行所有测试
  • mvn failsafe:integration-test 运行集成测试
  • mvn clean verify 当您想确定时,整个项目都可以正常工作

一些个人建议

将集成测试与单元测试分开使您可以轻松地在 IDE 中运行某个包中的所有测试。通常称为test-integration(或integrationtest)的附加目录用于此目的。
使用 maven 也很容易实现:

<plugin>
    <!-- adding second test source directory (just for integration tests) -->
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.9.1</version>
    <executions>
        <execution>
            <id>add-integration-test-source</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>add-test-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>src/test-integration/java</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

然后将您的集成测试移动到该目录。它应该看起来像:

src
   main
   test
   test-integration

集成测试通常需要更多内存:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    ...
    <configuration>
        <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine>
    </configuration>
</plugin>
于 2014-09-18T09:15:15.640 回答
12

这篇文章解释了如何跳过集成测试,无论您使用什么插件进行这些测试。

基本上,您所做的是定义一个配置文件并将所有与集成测试相关的 xml 代码放入该配置文件中。比您在-DskipIntegrationTests缺少属性时激活它。

您可以对单元测试执行相同的操作:编写配置文件并在-DskipUnitTests缺少时激活它。

然后,你可以这样做:

mvn install -DskipIntegrationTests -DskipUnitTests # (runs install without any tests)
mvn test # (runs unit tests)
mvn post-integration-test # (runs all tests)
于 2013-10-16T07:23:12.230 回答
5

maven-failsafe-plugin文档有一个标题为“默认跳过”的部分。

可悲的是,该页面描述的步骤并不像书面那样工作。但是,对这些步骤稍作改动即可使其发挥作用:

在 的properties部分中pom.xml,添加以下内容:

<skipITs>true</skipITs>

然后将该skipTests属性添加到pluginmaven-failsafe-plugin 部分:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <configuration>
        <skipTests>${skipITs}</skipTests>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>

所以现在,mvn install默认情况下将执行单元测试,但不执行集成测试。

但是 anmvn install -DskipITs=false将执行单元测试和集成测试。

脚注:糟糕的文档是 Maven 长期以来如此不受欢迎的一个重要原因。

于 2017-02-22T19:11:19.993 回答
2

mvn test-compile完全符合您的要求。你可以简单地替换mvn installmvn test-compile,你就完成了。无需自定义 pom 文件或任何东西。以下链接的问题与#1 类似:

Maven - 如何在不运行测试的情况下编译测试?

mvn test-compile应该被接受为最佳答案,因为 Maven 完全支持您想要在本地执行的操作,并且没有任何魔法。你最终会得到这个:

If I run mvn test-compile, I want all tests to compile, but I do not want to execute any.
If I run mvn test, I want all tests to compile, but execute only unit tests.
If I run mvn integration-test, I want to compile and execute all tests.
于 2017-06-20T14:40:35.890 回答
0

不要在故障安全插件的配置中指定执行步骤。例如

    <plugins>
        <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>3.0.0-M3</version>
        </plugin>
    </plugins>

现在,您特别需要调用 mvn failsafe:integration-test 来运行集成测试;它们将在其他 mvn 目标中被跳过。

于 2019-05-01T17:41:35.270 回答