Close

JUnit 5 - Suite Filtering @Tag Example, Using @IncludeTags and @ExcludeTags with @Suite

[Last Updated: Dec 19, 2025]

The JUnit Platform Suite Engine allows you to combine multiple filters to create sophisticated test selection strategies. By using annotations like @IncludeTags and@ExcludeTags, you can create highly targeted test suites for specific scenarios, environments, or testing purposes.

Filter Combination Strategy

When combining multiple filters, the Suite Engine applies them in a logical sequence:

  1. Package Selection: First, select packages using @SelectPackages or classes using @SelectClasses
  2. Package Filtering: Apply @IncludePackages and @ExcludePackages
  3. Class Name Filtering: Apply @IncludeClassNamePatterns and @ExcludeClassNamePatterns
  4. Tag Filtering: Apply @IncludeTags and @ExcludeTags

Tag-Based Filtering

Tags provide a flexible way to categorize tests:

  • @IncludeTags: Only include tests with specified tags
  • @ExcludeTags: Exclude tests with specified tags
  • Tags can represent test types, features, priorities, or environments

Use Cases for Combined Filters

  • Environment-Specific Testing: Run only tests tagged for current environment
  • Feature Testing: Test specific features across multiple packages
  • Quality Gates: Create suites for different quality levels
  • Selective Regression Testing: Target tests for changed functionality

Java source and doc

Definition of IncludeTags

Version: 6.0.0
 package org.junit.platform.suite.api;
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 @Inherited
 @Documented
 @API(status = MAINTAINED, since = "1.0")
 public @interface IncludeTags {
     String[] value(); 1
 }
1One or more tags to include.

Definition of ExcludeTags

Version: 6.0.0
 package org.junit.platform.suite.api;
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 @Inherited
 @Documented
 @API(status = MAINTAINED, since = "1.0")
 public @interface ExcludeTags {
     String[] value(); 1
 }
1One or more tags to exclude.

Example

In this example we have following classes:

$ tree /a /f
Folder PATH listing for volume Joe Projects
Volume serial number is D064-5C43
D:.
\---com
\---logicbig
\---example
CriticalUserTest.java
ExcludedLegacyTest.java
IntegrationPaymentTest.java
PerformanceUserTest.java
SlowOrderTest.java
SuiteCombiningFiltersExample.java

Test Classes

package com.logicbig.example;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

@Tag("critical")
@Tag("user")
public class CriticalUserTest {

    @Test
    void testCriticalUserLogin() {
        System.out.println("CriticalUserTest - Critical user login test");
        assertTrue(true, "Critical user should be able to login");
    }

    @Test
    @Tag("security")
    void testUserSecurity() {
        System.out.println("CriticalUserTest - User security test");
        assertEquals("secure", "secure", "User security should be enforced");
    }
}
package com.logicbig.example;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

@Tag("user")
@Tag("slow")  // This tag causes exclusion
public class PerformanceUserTest {

    @Test
    void testUserPerformance() {
        System.out.println("PerformanceUserTest - User performance test");
    }
}
package com.logicbig.example;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

@Tag("payment")
@Tag("integration")  // This tag causes exclusion
public class IntegrationPaymentTest {

    @Test
    void testPaymentIntegration() {
        System.out.println("IntegrationPaymentTest - Payment integration test");
    }
}
package com.logicbig.example;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Tag("order")
@Tag("slow")
public class SlowOrderTest {

    @Test
    void testSlowOrderProcessing() {
        System.out.println("SlowOrderTest - Slow order processing test");
    }
}
package com.logicbig.example;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

@Tag("critical")
public class ExcludedLegacyTest {

    @Test
    void testLegacyFunctionality() {
        System.out.println("ExcludedLegacyTest - Legacy functionality test");
    }
}
package com.logicbig.example;

import org.junit.platform.suite.api.*;

@Suite
@SuiteDisplayName("Comprehensive Filtered Test Suite")
@SelectPackages("com.logicbig.example")  // Select all packages

// Package filtering
@IncludePackages({
    "com.logicbig.example"
})

// Class name pattern filtering
@IncludeClassNamePatterns(".*Test$")      // Only include classes ending with "Test"
@ExcludeClassNamePatterns(".*Legacy.*")   // Exclude classes containing "Legacy"

// Tag filtering
@IncludeTags({
    "critical",     // Include tests tagged as critical
    "user",         // Include tests tagged as user-related
    "payment"       // Include tests tagged as payment-related
})
@ExcludeTags({
    "slow",         // Exclude slow tests
    "integration"   // Exclude integration tests
})

// Engine filtering (optional - commented out as we only use JUnit Jupiter)
// @IncludeEngines("junit-jupiter")  // Only use JUnit Jupiter engine
// @ExcludeEngines("junit-vintage")  // Exclude JUnit 4 engine

public class SuiteCombiningFiltersExample {
    // This suite combines multiple filters:
    // 1. Only classes ending with "Test"
    // 2. Excluding classes with "Legacy" in name
    // 3. Including tests tagged "critical", "user", or "payment"
    // 4. Excluding tests tagged "slow" or "integration"
}

Output

$ mvn test -Dtest=SuiteCombiningFiltersExample
[INFO] Scanning for projects...
[INFO]
[INFO] ----< com.logicbig.example:junit-5-suite-combining-filters-example >----
[INFO] Building junit-5-suite-combining-filters-example 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ junit-5-suite-combining-filters-example ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-suite-engine\junit-5-suite-combining-filters-example\src\main\resources
[INFO]
[INFO] --- compiler:3.11.0:compile (default-compile) @ junit-5-suite-combining-filters-example ---
[INFO] No sources to compile
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ junit-5-suite-combining-filters-example ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-suite-engine\junit-5-suite-combining-filters-example\src\test\resources
[INFO]
[INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ junit-5-suite-combining-filters-example ---
[INFO] Changes detected - recompiling the module! :source
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 6 source files with javac [debug target 17] to target\test-classes
[INFO]
[INFO] --- surefire:3.5.0:test (default-test) @ junit-5-suite-combining-filters-example ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
CriticalUserTest - Critical user login test
CriticalUserTest - User security test
[INFO] +--Comprehensive Filtered Test Suite CriticalUserTest - 0.065 ss
[INFO] | +-- [OK] testCriticalUserLogin - 0.039 ss
[INFO] | '-- [OK] testUserSecurity - 0.008 ss
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.221 s
[INFO] Finished at: 2025-12-19T11:52:25+08:00
[INFO] ------------------------------------------------------------------------

The test output demonstrates that the comprehensive filtered suite successfully applies multiple filtering criteria in conjunction, resulting in the execution of only CriticalUserTest with its two tagged test methods. This precise outcome confirms that all filters—package inclusion, class name pattern matching (including .*Test$ and excluding .*Legacy.*), and tag-based selection (including critical/user/payment tags while excluding slow/integration)—work correctly to create a highly targeted test suite that isolates specific critical business functionality while systematically excluding unwanted test categories.

Example Project

Dependencies and Technologies Used:

  • junit-jupiter-engine 6.0.1 (Module "junit-jupiter-engine" of JUnit)
     Version Compatibility: 5.8.0 - 6.0.1Version List
    ×

    Version compatibilities of junit-jupiter-engine with this example:

    • 5.8.0
    • 5.8.1
    • 5.8.2
    • 5.9.0
    • 5.9.1
    • 5.9.2
    • 5.9.3
    • 5.10.0
    • 5.10.1
    • 5.10.2
    • 5.10.3
    • 5.10.4
    • 5.10.5
    • 5.11.0
    • 5.11.1
    • 5.11.2
    • 5.11.3
    • 5.11.4
    • 5.12.0
    • 5.12.1
    • 5.12.2
    • 5.13.0
    • 5.13.1
    • 5.13.2
    • 5.13.3
    • 5.13.4
    • 5.14.0
    • 5.14.1
    • 6.0.0
    • 6.0.1

    Versions in green have been tested.

  • junit-platform-suite-engine 6.0.1 (Module "junit-platform-suite-engine" of JUnit)
  • JDK 25
  • Maven 3.9.11

JUnit 5 - Combining Suite Filters Example Select All Download
  • junit-5-suite-combining-filters-example
    • src
      • test
        • java
          • com
            • logicbig
              • example
                • SuiteCombiningFiltersExample.java

    See Also