Junit:拆分集成测试和单元测试


126

我继承了Junit测试的负载,但是这些测试(除了大多数无法正常工作的测试)是实际单元测试和集成测试(需要外部系统,数据库等)的混合。

因此,我正在尝试一种将它们实际分离出来的方法,以便可以快速好地运行单元测试,然后进行集成测试。

选项是..

  1. 将它们分成单独的目录。

  2. 从v3迁移到Junit4,并注释类以将它们分开。

  3. 使用文件命名约定来告诉类是什么,即AdapterATest和AdapterAIntergrationTest。

3的问题是Eclipse可以选择“运行所选项目/程序包或文件夹中的所有测试”。因此,仅运行集成测试将非常困难。

2:冒着开发人员可能开始在单元测试类中编写集成测试的风险,并且变得一团糟。

1:似乎是最巧妙的解决方案,但是我的直觉说必须有更好的解决方案。

这就是我的问题,您如何将集成测试和适当的单元测试分开?


我要感谢大家的输入,我知道这是一个主观问题,不是一个正确的答案。但是您帮助我认识到,除了我列出的选项之外,没有其他选择。我想我现在将继续使用目录结构,并转移到JUnit4,尽管目前还没有使用注释将它们拆分。
jeff porter 2010年

Answers:


10

由于组织政策(和Junit 3的遗留问题),我目前使用单独的目录,但是现在我要使用Junit 4,我希望自己过渡到注释。

对于开发人员将集成测试放入您的单元测试类中,我不会太担心-必要时在您的编码标准中添加一条规则。

我很想知道除了注释或在物理上将类分开之外,还有哪些其他解决方案。


145

您可以使用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>
  <dependencies>
   <dependency>
     <groupId>org.apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <includes>
      <include>**/*.class</include>
    </includes>
    <excludedGroups>com.test.annotation.type.IntegrationTest</excludedGroups>
  </configuration>
</plugin>

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

配置Maven集成测试

同样,此配置非常简单。

要仅运行集成测试,请使用以下命令:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.11</version>
  <dependencies>
   <dependency>
     <groupId>org.apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <groups>com.test.annotation.type.IntegrationTest</groups>
  </configuration>
</plugin>

如果将其包装在ID为ID的配置文件中IT,则只能使用进行快速测试mvn clean install。要仅运行集成/慢速测试,请使用mvn clean install -P IT

但最常见的情况是,您默认需要运行快速测试,并使用运行所有测试-P IT。如果真是这样,那么您必须使用一个技巧:

<profiles>
    <profile>
        <id>IT</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <excludedGroups>java.io.Serializable</excludedGroups> <!-- An empty element doesn't overwrite, so I'm using an interface here which no one will ever use -->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

如您所见,我排除了带有注释的测试java.io.Serializable。这是必需的,因为配置文件将继承Surefire插件的默认配置,因此即使您说<excludedGroups/><excludedGroups></excludedGroups>com.test.annotation.type.IntegrationTest也将使用该值。

您也不能使用none它,因为它必须是类路径上的接口(Maven会对此进行检查)。

笔记:

  • surefire-junit47仅当Maven不会自动切换到JUnit 4运行程序时才需要对的依赖。使用groupsexcludedGroups元素应触发切换。看这里
  • 上面的大多数代码来自Maven Failsafe插件的文档。请参阅本页上的 “使用JUnit类别”部分。
  • 在我的测试过程中,我发现当您使用@RunWith()批注运行套件或基于Spring的测试时,这甚至也可以使用。

18
我认为您的最后一个pom.xml片段中有错误。您粘贴了与“测试”阶段相同的代码段。它仍然不包括集成测试,也不受任何Maven阶段的约束。
亚历克斯

1
实际上,最后一个pom片段是复制粘贴错误。它应该显示maven-failsafe-plugin。
Paulo Merson

2
那么第二个xml应该是什么呢?:O
Liv

如果您使用默认的Maven配置文件
无需

这实际上应该是公认的答案,因为这实际上是问题的解决方案,而不是关于在哪里进行不同测试的哲学辩论。
排球比赛

40

我们使用Maven Surefire插件运行单元测试,并使用Maven Failsafe插件运行集成测试。单元测试遵循**/Test*.java **/*Test.java **/*TestCase.java命名约定,即集成测试- **/IT*.java **/*IT.java **/*ITCase.java。所以这实际上是您的第三个选择。

在几个项目中,我们使用TestNG并为集成/单元测试定义不同的测试组,但这可能不适合您。


1
+1表示maven + surefire +故障安全+ junit组合。我没有意识到故障保护会自动运行“ IT *”。甜。
PapaFreud 2011年

13

我会因为拥有它而升级到Junit4 :)

您可以将它们分为不同的测试套件。我不知道它们在Junit3中的组织方式,但在Junit4中应该很容易,只是建立测试套件并将所有真实的单元测试放在其中一个之中,然后使用第二个套件进行集成测试。

现在,在Eclipse中为两个套件定义一个运行配置,您可以轻松地运行一个套件。这些套件也可以从自动化过程中启动,从而使您每次更改源时都可以运行单元测试,也许可以每天一次或每小时一次运行集成测试(如果它们真的很大)。


9

使用IfProfileValue弹簧注释可以实现此目标,而无需 maven插件或配置。

使用IfProfileValue注释集成测试类或方法

import org.springframework.test.annotation.IfProfileValue;

@IfProfileValue(name="test-groups", value="integration")
public class ExampleIntegrationTest{
    @Test
    public void longRunningServiceTest() throws Exception {
    }
} 

要仅使用单元测试运行:

mvn clean test

要使用集成测试和单元测试运行:

mvn clean test -Dtest-groups=integration

另外,IDE中的“运行所有测试”将仅运行单元测试。添加-Dtest-groups=integration到VM参数以运行集成和单元测试。


这种方法既好又简单,但是我发现的问题是,默认情况下,我想运行所有测试(包括集成测试)。用这种方法是不可能的,不是吗?
csalazar

6

没有一个正确的答案。正如您所解释的,有几种方法可以起作用。我既完成了文件命名方案,又将内容拆分到不同的目录中。

听起来像将内容分成不同的目录可能对您更有效,对我来说似乎更清楚一些,所以我倾向于这样做。

我认为我不会尝试使用注解,因为这对我来说似乎更精细。您是否真的要将这两种类型的测试混合在同一个文件中?我不会

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.