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

发布于 2024-08-28 05:43:50 字数 503 浏览 4 评论 0原文

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

因此,我试图想出一种方法将它们真正分开,这样我就可以很好、快速地运行单元测试以及之后的集成测试。

选项是..

  1. 将它们拆分到单独的目录中。

  2. 移动到 Junit4(从 v3)并注释这些类以将它们分开。

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

3 存在以下问题:Eclipse 可以选择“运行所选项目/包或文件夹中的所有测试”。因此,运行集成测试会变得非常困难。

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

1:看起来是最巧妙的解决方案,但我的直觉告诉我一定有更好的解决方案。

这就是我的问题,如何分解集成测试和正确的单元测试?

I've inherited a load of Junit test, but these tests (apart from most not working) are a mixture of actual unit test and integration tests (requiring external systems, db etc).

So I'm trying to think of a way to actually separate them out, so that I can run the unit test nice and quickly and the integration tests after that.

The options are..

  1. Split them into separate directories.

  2. Move to Junit4 (from v3) and annotate the classes to separate them.

  3. Use a file naming convention to tell what a class is , i.e. AdapterATest and
    AdapterAIntergrationTest.

3 has the issue that Eclipse has the option to "Run all tests in the selected project/package or folder". So it would make it very hard to just run the integration tests.

2: runs the risk that developers might start writing integration tests in unit test classes and it just gets messy.

1: Seems like the neatest solution, but my gut says there must be a better solution out there.

So that is my question, how do you lot break apart integration tests and proper unit tests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

秋叶绚丽 2024-09-04 05:43:50

您可以使用 JUnit 类别和 Maven 非常轻松地拆分它们。

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

定义标记接口

The first step in grouping a test using categories is to create a marker interface.

该接口将用于标记您想要作为集成测试运行的所有测试。

public interface IntegrationTest {}

标记您的测试类

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

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

配置 Maven 单元测试

The beauty of this solution is that nothing really changes for the unit test side of things.

我们只需向 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 集成测试

Again the configuration for this is very simple.

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

<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 为 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.Serialized 注释的测试。这是必要的,因为配置文件将继承 Surefire 插件的默认配置,因此即使您说 ,将使用值com.test.annotation.type.IntegrationTest

您也不能使用 none 因为它必须是类路径上的接口(Maven 将检查这一点)。

注意:

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

You can split them very easily using JUnit categories and Maven.

This is shown very, very briefly below by splitting unit and integration tests.

Define A Marker Interface


The first step in grouping a test using categories is to create a marker interface.

This interface will be used to mark all of the tests that you want to be run as integration tests.

public interface IntegrationTest {}

Mark your test classes

Add the category annotation to the top of your test class. It takes the name of your new interface.

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

Configure Maven Unit Tests


The beauty of this solution is that nothing really changes for the unit test side of things.

We simply add some configuration to the maven surefire plugin to make it to ignore any integration tests.

<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>

When you do a mvn clean test only your unmarked unit tests will run.

Configure Maven Integration Tests


Again the configuration for this is very simple.

To run only the integration tests, use this:

<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>

If you wrap this in a profile with id IT, you can run only the fast tests using mvn clean install. To run just the integration/slow tests, use mvn clean install -P IT.

But most often, you will want to run the fast tests by default and all tests with -P IT. If that's the case, then you have to use a trick:

<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>

As you can see, I'm excluding tests that are annotated with java.io.Serializable. This is necessary because the profile will inherit the default config of the Surefire plugin, so even if you say <excludedGroups/> or <excludedGroups></excludedGroups>, the value com.test.annotation.type.IntegrationTest will be used.

You also can't use none since it has to be an interface on the classpath (Maven will check this).

Notes:

  • The dependency to surefire-junit47 is only necessary when Maven doesn't switch to the JUnit 4 runner automatically. Using the groups or excludedGroups element should trigger the switch. See here.
  • Most of the code above was taken from the documentation for the Maven Failsafe plugin. See the section "Using JUnit Categories" on this page.
  • During my tests, I found that this even works when you use @RunWith() annotations to run suites or Spring-based tests.
蓝礼 2024-09-04 05:43:50

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

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

We use Maven Surefire Plugin to run unit tests and Maven Failsafe Plugin to run integration tests. Unit tests follow the **/Test*.java **/*Test.java **/*TestCase.java naming conventions, integration tests - **/IT*.java **/*IT.java **/*ITCase.java. So it's actually your option number three.

In a couple of projects we use TestNG and define different test groups for integration/unit tests, but this is probably not suitable for you.

£冰雨忧蓝° 2024-09-04 05:43:50

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

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

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

I would move up to Junit4 just for having it :)

You could separate them into different test suites. I don't know how they are organised in Junit3 but it should be easy in Junit4 just to build up test suites and put all the real unit tests in one of them and then use a second suite for the integration tests.

Now define a run configuration for both suites in eclipse and you can easily run a single suite. These suites also could be launched from an automated process allowing you to run the unit tests every time the source changes and maybe the integration tests (if they are really large) only once a day or once an hour.

长梦不多时 2024-09-04 05:43:50

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

我不会过度担心开发人员将集成测试放入单元测试类中- 如有必要,在您的编码标准中添加规则。

我有兴趣知道除了注释或物理分离类之外可能还有哪些其他解决方案。

I currently use separate directories due to organisational policy (and Junit 3 legacy) but I'm looking to transition to annotations myself now I'm on Junit 4.

I wouldn't be overly concerned about developers putting integration tests in your unit test classes - add a rule in your coding standards if necessary.

I'm interested to know what sort of other solutions there might be apart from annotations or physically separating the classes..

歌枕肩 2024-09-04 05:43:50

使用 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 {
    }
} 

仅使用单元测试运行:

mvn clean test

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

mvn clean test -Dtest-groups=integration

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

Using IfProfileValue spring annotation
makes it possible to achieve this without a maven plugin or configuration required.

Annotate the integration test classes or methods using the IfProfileValue

import org.springframework.test.annotation.IfProfileValue;

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

To run using unit tests only:

mvn clean test

To run using integration test and unit tests:

mvn clean test -Dtest-groups=integration

Also, "Run all test" in an IDE would run only unit test. Add -Dtest-groups=integration to VM arguments to run both integration and unit tests.

冧九 2024-09-04 05:43:50

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

听起来把东西分成不同的目录可能对你来说效果更好,这对我来说似乎更清晰,所以我倾向于这样做。

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

There's not one right answer. As you've explained, there are several ways to do it which will work. I've done both the file naming scheme and splitting things into different directories.

It sounds like splitting thing up into different directories might work better for you, and that seems a little clearer to me, so I'd lean towards that.

I don't think I would try annotations because that seems more fine-grained to me. Do you really want these two types of tests mixed together in the same file? I wouldn't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文