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

jef*_*ter 124 testing junit integration-testing unit-testing junit4

我继承了Junit测试的负载,但是这些测试(除了大多数不工作之外)是实际单元测试和集成测试(需要外部系统,db等)的混合.

所以我试图想出一种方法来实际将它们分开,这样我就可以很好地快速运行单元测试,然后进行集成测试.

选项是......

  1. 将它们拆分为单独的目录.

  2. 移至Junit4(从v3开始)并注释类以将它们分开.

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

3存在Eclipse可以选择"在所选项目/包或文件夹中运行所有测试"的问题.因此,只需运行集成测试就很难了.

2:冒着开发人员可能开始在单元测试类中编写集成测试的风险,它只会变得混乱.

1:似乎是最好的解决方案,但我的直觉说必须有一个更好的解决方案.

所以这就是我的问题,你如何分解集成测试和适当的单元测试?

小智 140

您可以使用JUnit类别和Maven轻松拆分它们.

下面通过拆分单元和集成测试非常简单地展示了这一点.

定义标记接口

使用类别对测试进行分组的第一步是创建标记接口.

此接口将用于标记要作为集成测试运行的所有测试.

public interface IntegrationTest {}
Run Code Online (Sandbox Code Playgroud)

标记您的测试类

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

import org.junit.experimental.categories.Category;
@Category(IntegrationTest.class)
public class ExampleIntegrationTest{
  @Test
  public void longRunningServiceTest() throws Exception {
  }
}
Run Code Online (Sandbox Code Playgroud)

配置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>
Run Code Online (Sandbox Code Playgroud)

当你进行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>
Run Code Online (Sandbox Code Playgroud)

如果将其包装在具有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>
Run Code Online (Sandbox Code Playgroud)

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

你也不能使用,none因为它必须是类路径上的接口(Maven会检查这个).

笔记:

  • surefire-junit47只有在Maven没有自动切换到JUnit 4运行程序时才需要依赖.使用groupsor excludedGroups元素应该触发开关.看到这里.
  • 上面的大部分代码都来自Maven Failsafe插件的文档.请参阅此页面上的 "使用JUnit类别"部分.
  • 在我的测试中,我发现当你使用@RunWith()注释来运行套件或基于Spring的测试时,这甚至可以工作.

  • 我认为你的上一个pom.xml片段有一个错误.你粘贴了与"测试"阶段相同的片段.它仍然不包括集成测试,也不受任何maven阶段的约束. (18认同)
  • 那么第二个xml应该是什么呢?:o (2认同)

lex*_*ore 39

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

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


Jan*_*usz 12

我会升级到Junit4只是为了拥有它:)

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

现在为eclipse中的两个套件定义运行配置,您可以轻松运行单个套件.这些套件也可以通过自动化过程启动,允许您在每次源更改时运行单元测试,并且可能每天只运行一次或每小时一次集成测试(如果它们非常大).


小智 10

由于组织策略(以及Junit 3遗留问题),我目前使用单独的目录,但我现在想要转换到注释,现在我正在使用Junit 4.

我不会过分关注开发人员将集成测试放在单元测试类中 - 如果需要,在编码标准中添加规则.

我很想知道除了注释或物理上分离类之外还有哪些其他解决方案.


小智 8

使用IfProfileValue spring注释可以在不需要 maven插件或配置的情况下实现此目的.

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

import org.springframework.test.annotation.IfProfileValue;

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

仅使用单元测试运行:

mvn clean test
Run Code Online (Sandbox Code Playgroud)

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

mvn clean test -Dtest-groups=integration
Run Code Online (Sandbox Code Playgroud)

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


ndp*_*ndp 6

没有一个正确的答案.正如您所解释的那样,有几种方法可以实现.我已经完成了文件命名方案并将事物拆分到不同的目录中.

这听起来像把事情分成不同的目录可能对你更好,这对我来说似乎有点清楚,所以我倾向于那个.

我不认为我会尝试注释,因为这对我来说似乎更精细.你真的希望这两种类型的测试在同一个文件中混合在一起吗?我不会.