1. 概述

在 CI 构建流程中,我们通常会使用 Maven 自动执行所有 JUnit 测试。但这种方式往往比较耗时。

因此,我们经常需要对测试进行过滤,在构建的不同阶段执行单元测试、集成测试或两者兼顾

在本文中,我们将重点介绍 JUnit 5 提供的标签(Tag)机制,以及在 JUnit 5 之前的分类(Category)机制。我们还将介绍通过 Maven Surefire 插件进行测试过滤的实践方法。


2. JUnit 5 标签机制

2.1. 使用 @Tag 注解标记测试

JUnit 5 提供了 @Tag 注解,允许我们为测试类或方法打上标签,从而实现分类管理。例如:

@Test
@Tag("IntegrationTest")
public void testAddEmployeeUsingSimpelJdbcInsert() {
}

@Test
@Tag("UnitTest")
public void givenNumberOfEmployeeWhenCountEmployeeThenCountMatch() {
}

优点:灵活标记单个测试方法或整个测试类,便于后续筛选执行。


2.2. 使用测试套件过滤标签

JUnit 5 支持通过测试套件(Test Suite)来执行特定标签下的测试:

@SelectPackages("com.baeldung.tags")
@IncludeTags("UnitTest")
public class EmployeeDAOUnitTestSuite {
}

运行这个测试套件时,只会执行带有 @Tag("UnitTest") 的测试方法

也可以使用 @ExcludeTags 排除某些标签的测试:

@SelectPackages("com.baeldung.tags")
@ExcludeTags("IntegrationTest")
public class EmployeeDAOUnitTestSuite {
}

⚠️ 注意:测试套件类不需要包含任何实际测试方法。


2.3. 使用 Maven Surefire 插件过滤标签

在 Maven 构建过程中,我们可以通过 Surefire 插件配置来过滤标签:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.2.5</version>
    <configuration>
        <groups>UnitTest</groups>
    </configuration>
</plugin>

也可以排除特定标签:

<excludedGroups>IntegrationTest</excludedGroups>

优点:适用于 CI 构建环境,可灵活配置不同构建阶段执行不同标签的测试。


2.4. 使用 IDE 过滤标签

现代 IDE(如 IntelliJ IDEA 和 Eclipse)也支持通过标签过滤测试。

IntelliJ IDEA 示例:

JUnit5 Tags in IntelliJ

在 Run/Debug 配置中,选择测试类型为 Tags,并填写 Tag Expression,例如:

  • !IntegrationTest 表示排除集成测试
  • UnitTest | IntegrationTest 表示同时运行单元和集成测试

Eclipse 示例:

JUnit5 Tags in Eclipse


3. JUnit 4 分类机制

3.1. 使用 @Category 注解分类测试

JUnit 4 中通过 @Category 注解实现测试分类,其核心思想是使用标记接口(Marker Interface)来定义分类:

public interface UnitTest {
}

public interface IntegrationTest {
}

然后通过 @Category 注解将测试方法或类归类:

@Test
@Category(IntegrationTest.class)
public void testAddEmployeeUsingSimpelJdbcInsert() {
}

@Test
@Category(UnitTest.class)
public void givenNumberOfEmployeeWhenCountEmployeeThenCountMatch() {
}

优点:结构清晰,适合在 JUnit 4 中进行测试分类管理。


3.2. 使用 Categories 测试套件

JUnit 4 提供了 Categories Runner 来执行特定分类的测试:

@RunWith(Categories.class)
@IncludeCategory(UnitTest.class)
@SuiteClasses(EmployeeDAOCategoryIntegrationTest.class)
public class EmployeeDAOUnitTestSuite {
}

也可以排除某个分类:

@RunWith(Categories.class)
@ExcludeCategory(IntegrationTest.class)
@SuiteClasses(EmployeeDAOCategoryIntegrationTest.class)
public class EmployeeDAOUnitTestSuite {
}

⚠️ 注意:@SuiteClasses 中必须包含目标测试类。


3.3. 在 Maven 中包含或排除分类

我们也可以在 Maven 构建中通过 Surefire 插件控制测试分类:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.2.5</version>
    <configuration>
        <groups>com.baeldung.categories.UnitTest</groups>
    </configuration>
</plugin>

排除分类:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.2.5</version>
    <configuration>
        <excludedGroups>com.baeldung.categories.IntegrationTest</excludedGroups>
    </configuration>
</plugin>

技巧:配合 Maven Profiles 可实现不同环境执行不同分类的测试。


4. 使用 Maven Surefire 插件进行命名过滤

除了使用 JUnit 自带的分类/标签机制,还可以通过命名约定来过滤测试类。例如:

  • 单元测试类名以 *Test.java 结尾
  • 集成测试类名以 *IntegrationTest.java 结尾

然后在 Surefire 插件中配置过滤规则:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.2.5</version>
    <configuration>
        <excludes>
            **/*IntegrationTest.java
        </excludes>
    </configuration>
</plugin>

优点:无需修改测试代码,只需规范类名即可实现过滤。

⚠️ 注意:虽然 Surefire 插件可用于集成测试,但更推荐使用 Maven Failsafe Plugin 来执行集成测试。


5. 总结

本文介绍了以下三种 JUnit 测试过滤方式:

  • JUnit 5 标签机制:使用 @Tag 注解 + 测试套件或 Maven Surefire 插件
  • JUnit 4 分类机制:使用 @Category 注解 + Categories Runner 或 Maven Surefire 插件
  • Maven Surefire 插件命名过滤:基于类名后缀进行测试筛选

📌 推荐做法

  • 如果使用 JUnit 5,优先使用 @Tag 实现灵活标签管理
  • 如果仍在使用 JUnit 4,可使用 @Category 进行分类管理
  • 对于 CI 构建阶段,结合 Surefire/Failsafe 插件配置更高效

通过合理使用这些机制,可以显著提升测试效率,减少构建时间,避免不必要的测试重复执行。


原始标题:Tagging and Filtering JUnit Tests | Baeldung