I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

1. Overview

It's very common to execute all our JUnit tests automatically as a part of the CI build using Maven. This, however, is often time-consuming.

Therefore, we often want to filter our tests and execute either unit tests or integration tests or both at various stages of the build process.

In this tutorial, we'll look at a few filtering techniques for test cases with JUnit 5. In the following sections, we'll also look at various filtering mechanisms before JUnit 5.

2. JUnit 5 Tags

2.1. Annotating JUnit Tests with Tag

With JUnit 5 we can filter tests by tagging a subset of them under a unique tag name. For example, suppose we have both unit tests and integration tests implemented using JUnit 5. We can add tags on both sets of test cases:

If we now execute this plugin, it will execute all tests which are tagged as UnitTest. Similarly, we can exclude test cases under a tag name:

<excludedGroups>IntegrationTest</excludedGroups>

2.4. Filtering Tags with an IDE

IDEs now allow filtering the JUnit tests by tags. This way we can execute a specific set of tagged tests directly from our IDE.

IntelliJ allows such filtering through a custom Run/Debug Configuration:

As shown in this image, we selected the Test Kind as tags and the tag to be executed in the Tag Expression.

JUnit 5 allows various Tag Expressions which can be used to filter the tags. For example, to run everything but the integration tests, we could use !IntegrationTest as the Tag Expression. Or for executing both UnitTest and IntegrationTest, we can use UnitTest | IntegrationTest.

Similarly, Eclipse also allows including or excluding tags in the JUnit Run/Debug configurations:

3. JUnit 4 Categories

3.1. Categorizing JUnit Tests

JUnit 4 allows us to execute a subset of JUnit tests by adding them into different categories. As a result, we can execute the test cases in a particular category while excluding other categories.

We can create as many categories by implementing marker interfaces where the name of the marker interface represents the name of the category. For our example, we'll implement two categories, UnitTest:

public interface UnitTest {
}

and IntegrationTest:

public interface IntegrationTest {
}

Now, we can categorize our JUnit by annotating it with Category annotation:

This is similar to the example we discussed in the previous section. The only difference is that we replaced the tag name with the fully qualified name of the Category implementation.

4. Filtering JUnit Tests with Maven Surefire Plugin

Both of the approaches we've discussed have been implemented with the JUnit library. An implementation agnostic way of filtering test cases is by following a naming convention. For our example, we'll use UnitTest suffix for unit tests and IntegrationTest for integration tests.

The excludes tag here filters all integration tests and executes only the unit tests. Such a configuration would save a considerable amount of build time.

Furthermore, we can execute the Surefire plugin within various Maven profiles with different exclusions or inclusions.

Although Surefire works well for filtering, it is recommended to use the Failsafe Plugin for executing integration tests in Maven.

5. Conclusion

In this article, we saw a way to tag and filter test cases with JUnit 5. We used the Tag annotation and also saw various ways for filtering the JUnit tests with a specific tag through the IDE or in the build process using Maven.