如何使我的Maven集成测试运行


170

我有一个maven2多模块项目,并且在每个子模块中都有分别命名的JUnit测试Test.javaIntegration.java单元测试和集成测试。当我执行时:

mvn test

*Test.java子模块中的所有JUnit测试都将执行。当我执行

mvn test -Dtest=**/*Integration

没有一个Integration.java测试在子模块中执行。

这些命令对我来说似乎是完全相同的命令,但是带有-Dtest = / * Integration **的命令不起作用,它显示在父级别运行0个测试,而没有任何测试


4
Kief的答案应该是公认的答案,因为它是在Maven中定义集成测试的当前标准。
heenenee 2015年

Answers:


110

您可以设置Maven的Surefire分别运行单元测试和集成测试。在标准单元测试阶段,您将运行所有与集成测试都不匹配的模式。然后,您创建仅运行集成测试的第二个测试阶段

这是一个例子:

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
        <excludes>
          <exclude>**/*IntegrationTest.java</exclude>
        </excludes>
      </configuration>
      <executions>
        <execution>
          <id>integration-test</id>
          <goals>
            <goal>test</goal>
          </goals>
          <phase>integration-test</phase>
          <configuration>
            <excludes>
              <exclude>none</exclude>
            </excludes>
            <includes>
              <include>**/*IntegrationTest.java</include>
            </includes>
          </configuration>
        </execution>
      </executions>
    </plugin>

1
我按照您所说的进行了配置,执行时仅运行* Test而不是* Integration.java文件:mvn install我需要将* Test.java作为默认运行,但是对于我的噩梦构建,我需要同时运行* Test .java和* Integration.java。我必须执行mvn install,然后执行cd到每个子目录,然后执行mvn -Dtest = ** / *集成测试
Peter Delaney

66
您应该使用故障安全插件进行集成测试,而不是使用sure-fire插件。集成后阶段完成之前它不会使构建失败。允许您在构建失败之前拆除测试资源(例如Web服务器)。因此,故障安全。
John Gordon

对我来说,作为集成前阶段的一部分,码头服务器启动。最后一条日志行是:[INFO]启动了Jetty服务器。在那之后,什么都没有发生。卡住了。Maven surefire故障安全插件不会执行测试,也不会停止码头服务器。知道有什么问题吗?我使用的配置与您指定的相同。
塔伦·库玛

6
该答案已经过时,应予以更新或删除。
扎克·汤普森


250

Maven构建的生命周期现在包括“集成测试”相对于运行集成测试,这是从在“测试”阶段运行单元测试单独运行。它在“包”之后运行,因此,如果您运行“ mvn verify”,“ mvn install”或“ mvn deploy”,则集成测试将一直进行。

默认情况下,集成测试运行在名为测试类**/IT*.java**/*IT.java**/*ITCase.java,但可以配置。

有关如何进行全部连接的详细信息,请参阅Failsafe插件Failsafe使用页面(在撰写本文时未正确链接到上一页),还请参阅此Sonatype博客文章


1
@WillV正确。Codehaus的墓地。而且maven-failsafe-plugin现在在Apache中。抱歉。:)
晋权2014年

38
默认情况下,mvn integration-test还运行单元测试(通过surefire使用),但mvn failsafe:integration-test仅运行故障安全集成测试。
Shadow Man

22
令人难以置信的是,Failsafe插件文档,使用情况页面和FAQ中没有提到它运行名为* / IT .java,** / * IT.java和** / * ITCase.java的测试类……
Henno Vermeulen

1
如果它在package阶段之后运行,那意味着我应该将所有IT Java源代码放在下面,src/main/java而不是src/test/java正确?
布鲁斯·孙

5
@HennoVermeulen我也对命名测试感到困惑。在测试的包含和排除中进行了描述。可以覆盖默认值是很不错的,但是如果他们早些时候提到了默认值,那就太好了。
约书亚·泰勒

63

我已经完全完成了您想做的事情,并且效果很好。单元测试“ * Tests”始终运行,而“ * IntegrationTests”仅在您执行mvn验证或mvn安装时运行。这是我的POM的片段。serg10几乎是对的。。。。

  <plugin>
    <!-- Separates the unit tests from the integration tests. -->
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
       <!-- Skip the default running of this plug-in (or everything is run twice...see below) -->
       <skip>true</skip>
       <!-- Show 100% of the lines from the stack trace (doesn't work) -->
       <trimStackTrace>false</trimStackTrace>
    </configuration>
    <executions>
       <execution>
          <id>unit-tests</id>
          <phase>test</phase>
          <goals>
             <goal>test</goal>
          </goals>
          <configuration>
                <!-- Never skip running the tests when the test phase is invoked -->
                <skip>false</skip>
             <includes>
                   <!-- Include unit tests within integration-test phase. -->
                <include>**/*Tests.java</include>
             </includes>
             <excludes>
               <!-- Exclude integration tests within (unit) test phase. -->
                <exclude>**/*IntegrationTests.java</exclude>
            </excludes>
          </configuration>
       </execution>
       <execution>
          <id>integration-tests</id>
          <phase>integration-test</phase>
          <goals>
             <goal>test</goal>
          </goals>
          <configuration>
            <!-- Never skip running the tests when the integration-test phase is invoked -->
             <skip>false</skip>
             <includes>
               <!-- Include integration tests within integration-test phase. -->
               <include>**/*IntegrationTests.java</include>
             </includes>
          </configuration>
       </execution>
    </executions>
  </plugin>

祝好运!


确实是我想做的事情,但是我的集成测试在mvn测试阶段一直运行,因为我没有跳过默认值。我认为配置测试执行将覆盖它。正如您所解释的,它只是添加了一个新的执行(因此所有内容将运行两次)。所以对我来说,跳过是一件丢失的事情。+1当此配置将问题解答到100%时
Nils Schmidt 2010年

2
然后随意选中此答复作为答案的框!
HDave 2011年

对我来说,作为集成前阶段的一部分,码头服务器启动。最后一条日志行是:[INFO]启动了Jetty服务器。在那之后,什么都没有发生。卡住了。Maven surefire故障安全插件不会执行测试,也不会停止码头服务器。知道有什么问题吗?我使用的配置与您指定的相同。
塔伦·库玛

@Tarun-提出一个关于您的问题的新问题
HDave 2013年

2
这应该是公认的答案。相关的专家目标是: clean compile integration-test -Dmaven.test.failure.ignore=false
Neill Lima

31

您可以使用JUnit类别和Maven轻松拆分它们。
下面通过拆分单元测试和集成测试非常非常简要地显示了这一点。

定义标记接口

使用类别对测试进行分组的第一步是创建标记界面。
此接口将用于将要运行的所有测试标记为集成测试。

public interface IntegrationTest {}

标记您的测试班

将类别注释添加到测试类的顶部。它采用新界面的名称。

import org.junit.experimental.categories.Category;

@Category(IntegrationTest.class)
public class ExampleIntegrationTest{

    @Test
    public void longRunningServiceTest() throws Exception {
    }

}

配置Maven单元测试

该解决方案的优点在于,对于单元测试而言,什么都没有真正改变。
我们只需向maven surefire插件添加一些配置即可使其忽略任何集成测试。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.11</version>
    <configuration>
        <includes>
            <include>**/*.class</include>
        </includes>
        <excludedGroups>
            com.test.annotation.type.IntegrationTest
        </excludedGroups>
    </configuration>
</plugin>

当您执行时mvn clean test,只会运行未标记的单元测试。

配置Maven集成测试

同样,此配置非常简单。
我们使用标准的故障安全插件并将其配置为仅运行集成测试。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
        <includes>
            <include>**/*.class</include>
        </includes>
        <groups>
            com.test.annotation.type.IntegrationTest
        </groups>
    </configuration>
</plugin>

该配置使用标准执行目标在构建的集成测试阶段运行故障保护插件。

您现在可以做一个了mvn clean install
这次以及单元测试正在运行,集成测试是在集成测试阶段运行的。


我以为JUnit对我来说没有更多秘密了。好地方!
Gertas

4
仅当标记接口已经存在于Maven可用的地方时,此方法才有效。如果您的标记器接口存在于同一多模块构建的另一个模块中,则该方法将不起作用。
EngineerBetter_DJ

@EngineerBetter_DJ那是什么意思?如果您有一个基于多项目的Maven配置,您将无法执行此操作?
matthieusb

16

您应该尝试使用maven failsafe插件。您可以告诉它包括一组特定的测试。


1
+1这就是我用的。运行良好,并允许您进行事前/事后设置,例如启动和关闭本地servlet容器。
mdma 2011年

maven-failsafe-plugin已经去了Plugin Graveyard
Jin Kwon

9
该墓地页面仅表示该failsafe插件已移至maven-failsafe-plugin。似乎maven-failsafe-plugin仍处于活动状态(文档最后推送时间为2014年3月)。
James Kingsbery 2014年

13

默认情况下,Maven仅运行在类名中某处具有Test的测试。

重命名为IntegrationTest,它可能会起作用。

另外,您可以更改Maven配置以包括该文件,但仅将测试命名为SomethingTest可能会更容易,更好。

测试的包含和排除

默认情况下,Surefire插件将自动包含具有以下通配符模式的所有测试类:

  • \*\*/Test\*.java -包括其所有子目录以及以“ Test”开头的所有Java文件名。
  • \*\*/\*Test.java -包括其所有子目录和所有以“ Test”结尾的java文件名。
  • \*\*/\*TestCase.java -包括其所有子目录和所有以“ TestCase”结尾的Java文件名。

如果测试类不符合命名约定,则配置Surefire插件并指定要包括的测试。


嗨,谢谢,我有两种类型的普通POJO Junit测试,称为SomethingTest.java,它会被触发。我也有名为SomethingIntegration.java的集成测试,不会被解雇。通过mvn测试或mvn安装会触发SomethingTest.java。第二项测试不会被解雇。MVN测试-Dtest = ** / *集成
彼得德莱尼

..并且“ Maven仅运行在类名中某处具有Test的测试”就意味着“ Maven surefire插件仅运行在类名中某处具有Test的测试”。
约书亚·戴维斯

1
它不是“类名中的某处”,而是“类名以Test结尾”,例如MyTest有效,但MyTests不起作用
朱利安

10

使用Maven运行集成测试的另一种方法是利用配置文件功能:

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <includes>
                    <include>**/*Test.java</include>
                </includes>
                <excludes>
                    <exclude>**/*IntegrationTest.java</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

<profiles>
    <profile>
        <id>integration-tests</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <includes>
                            <include>**/*IntegrationTest.java</include>
                        </includes>
                        <excludes>
                            <exclude>**/*StagingIntegrationTest.java</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
...

运行“ mvn clean install”将运行默认版本。如上所述,集成测试将被忽略。运行“ mvn clean install -P集成测试”将包括集成测试(我也忽略了暂存集成测试)。此外,我有一台CI服务器,该服务器每天晚上运行集成测试,为此,我发出命令'mvn test -P integration-tests'


1
您为什么不使用集成测试阶段?然后,可以将配置文件用于诸如对各种应用程序服务器进行集成测试之类的工作,例如Arquillian。我不是Maven专家,但我认为专家可能会说这不是'Maven-y'。
约书亚·戴维斯

1
@Joshua我想我这样做是因为我的集成测试至少需要5分钟才能运行,并且我每天多次发布“ mvn clean install”,因为我需要在本地Maven存储库中更新工件。按照上面的说法,运行“安装”将导致集成测试阶段运行,使我浪费宝贵的开发时间。
豪尔赫

嗯...不确定“安装”是否正在运行集成测试。无论如何,我仍然会使用阶段而不是配置文件。配置文件是最好用于诸如支持不同的应用服务器,等等
约书亚·戴维斯

1
我会继续进行下去。谢谢你的建议!
豪尔赫

@jorge我猜这里使用的正确目标是验证,对吧?
Kilokahn,2012年

1

您可以按照Maven文档的说明来运行带有构建的单元测试,并分别运行集成测试。

<project>
    <properties>
        <skipTests>true</skipTests>
    </properties>
    [...]
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.20.1</version>
                <configuration>
                    <skipITs>${skipTests}</skipITs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    [...]
</project>

这将允许您在默认情况下禁用所有集成测试的情况下运行。要运行它们,请使用以下命令:

mvn install -DskipTests=false

0

您应该使用maven surefire插件运行单元测试,并使用maven failsafe插件运行集成测试。

如果您希望使用标志来切换这些测试的执行,请遵循以下内容。

Maven配置

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <skipTests>${skipUnitTests}</skipTests>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <configuration>
                <includes>
                    <include>**/*IT.java</include>
                </includes>
                <skipTests>${skipIntegrationTests}</skipTests>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <properties>
            <skipTests>false</skipTests>
            <skipUnitTests>${skipTests}</skipUnitTests>
            <skipIntegrationTests>${skipTests}</skipIntegrationTests>
        </properties>

因此,将根据以下标志规则跳过或切换测试:

可以通过以下标志跳过测试:

  • -DskipTests 跳过单元测试和集成测试
  • -DskipUnitTests 跳过单元测试但执行集成测试
  • -DskipIntegrationTests 跳过集成测试但执行单元测试

运行测试

在下面运行以执行单元测试

mvn clean test

您可以执行以下命令来运行测试(单元测试和集成测试)

mvn clean verify

为了运行集成测试,请遵循

mvn failsafe:integration-test

或跳过单元测试

mvn clean install -DskipUnitTests

另外,为了在期间跳过集成测试mvn install,请按照

mvn clean install -DskipIntegrationTests

您可以使用跳过所有测试

mvn clean install -DskipTests
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.