我在同一个文件夹(src/test/java)中有一个包含集成和单元测试的多模块 maven 项目。集成测试标有 @Category(IntegrationTest.class)
。我想结束以下设置:
如果我运行 mvn install,我希望编译所有测试,但我不想执行任何测试。如果我运行 mvn test,我希望编译所有测试,但只执行单元测试。如果我运行 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
将只执行单元测试,但我认为它没有太大区别。
听起来您不了解 Maven 中 build life-cycle 的概念。如果您运行 mvn install
,则所有生命周期阶段(包括 install
阶段本身)都会在安装阶段之前运行。这意味着运行以下阶段:
验证初始化生成源流程源生成资源流程资源编译流程类生成测试源流程测试源生成测试资源流程测试资源测试编译流程测试类测试准备包包预集成测试集成测试后集成测试验证安装
这意味着包括 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>
所以你的第一个要求:
如果我运行 mvn install,我希望编译所有测试,但我不想执行任何测试。
可以通过使用以下方法来实现:
mvn -Pno-unit-test test
如果我运行 mvn test,我希望编译所有测试,但只执行单元测试。
这可以通过使用普通调用来简单地实现:
mvn test
导致集成测试阶段未运行(请参阅构建生命周期)。
如果我运行 mvn integration-test,我想编译并执行所有测试。
这意味着运行默认设置,包括运行将运行单元测试 (maven-surefire-plugin) 的 test
阶段,并进一步运行由 maven-failsafe-plugin 处理的集成测试。但是您应该知道,如果您想调用集成测试,您应该使用以下命令:
mvn verify
相反,因为您错过了上一次通话中的 post-integration-test
阶段。
除上述内容外,您还应遵循单元和集成测试的命名约定,其中 unit tests 应命名如下:
<includes>
<include>**/*Test*.java</include>
<include>**/*Test.java</include>
<include>**/*TestCase.java</include>
</includes>
和 integration tests 应命名如下:
<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 更简单更短。
OP在他的问题中所说的:
如果我运行 mvn install,我希望编译所有测试,但我不想执行任何测试。如果我运行 mvn test,我希望编译所有测试,但只执行单元测试。如果我运行 mvn integration-test,我想编译并执行所有测试。
是完全有效的并且非常容易实现。
编辑:除了第一个条件,它违背了 maven 的性质。这里最好的方法就是简单地做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 验证您何时想确定整个项目是否正常工作
一些个人建议
将集成测试与单元测试分开使您可以轻松地在 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>
This post 解释了如何跳过集成测试,无论您使用什么插件进行这些测试。
基本上,您所做的是定义一个配置文件并将所有与集成测试相关的 xml 代码放入该配置文件中。比您在缺少属性 -DskipIntegrationTests
时激活它。
您可以对单元测试执行相同的操作:编写配置文件并在缺少 -DskipUnitTests
时激活它。
然后,你可以这样做:
mvn install -DskipIntegrationTests -DskipUnitTests # (runs install without any tests)
mvn test # (runs unit tests)
mvn post-integration-test # (runs all tests)
maven-failsafe-plugin docs 有一个标题为“默认跳过”的部分。
可悲的是,该页面描述的步骤并不像书面那样工作。但是,对这些步骤稍作改动即可使其发挥作用:
在 pom.xml
的 properties
部分中,添加以下内容:
<skipITs>true</skipITs>
然后将 skipTests
属性添加到 maven-failsafe-plugin 的 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
将执行单元测试,但不执行集成测试。
但是 mvn install -DskipITs=false
将执行单元测试和集成测试。
脚注:糟糕的文档是 Maven 长期以来如此不受欢迎的一个重要原因。
mvn test-compile
完全符合您的要求。您只需将 mvn install
替换为 mvn test-compile
即可。无需自定义 pom 文件或任何东西。以下链接的问题与#1 类似:
Maven - How to compile tests without running them ?
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.
不要在故障安全插件的配置中指定执行步骤。例如
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
</plugins>
现在,您特别需要调用 mvn failsafe:integration-test 来运行集成测试;它们将在其他 mvn 目标中被跳过。
不定期副业成功案例分享