Introduction To Junit5 Tags
Introduction To Junit5 Tags
Petri Kainulainen
Table of Contents
At the time Petri had no idea what he was doing but the outcome of his work amazed
him. He wanted to learn more about this thing called programming. In a way, that
moment was the starting point of his career.
Petri has over two decades of experience in software development. During this time he
has participated in dozens of different software development projects as a software
architect. Currently he is working in a privately owned software company, where he
concentrates on adding value to customers and learning new things every day.
He also has a popular blog where he writes about Spring Framework and automated
testing. Petri has also published an online course which helps you to write better tests
JUnit 5.
1
Introduction
This ebook provides a quick introduction to JUnit 5 tags. After you have read this
ebook, you:
Let’s start by finding out how you can add tags to your test methods.
2
Tagging Test Methods With JUnit 5
JUnit 5 tags allow you to divide your test methods into different groups and configure
the groups whose tests are run when you run your tests. When you want to add a tag
to a test class or a test method, you have to:
1. Annotate your test class or test method with the @Tag annotation.
2. Configure the name of your tag by setting the value of the @Tag annotation’s value
attribute.
When you configure the name of your tag, you must use a non-null value that isn’t
blank. Also, when JUnit 5 validates the name of your tag, it removes the leading and
trailing whitespace characters from it. After this has been done, JUnit 5 ensures that
the remaining name doesn’t:
If you need more information about the syntax rules concerning JUnit 5
tags, you should take a look at the JUnit 5 User Guide.
Additional Reading
When you annotate a test class with the @Tag annotation, Junit 5 has to decide which
test methods get the given tag. JUnit 5 finds these test methods by following these
steps:
First, JUnit 5 transforms the class hierarchy of your test class into a tree. The
annotated test class is the root node of the created tree and the nested test classes
which are enclosed by the annotated test class are added to the created tree as
nodes.
3
Example 1: The @Tag Annotation Is Added to a Test Class
Second, JUnit 5 finds all paths from the root node (aka the annotated test class) to the
leaf nodes. A leaf node is either a "normal" test class or a nested test class which don’t
contain any nested test classes.
The following figure illustrates the paths found from the tree illustrated by the example
1:
4
Third, JUnit 5 iterates the found paths one by one and processes all test classes found
from the inspected path by following these steps:
Next, we will take look at some examples which demonstrate how you can add one tag
to your test methods.
5
Adding One Tag to Your Test Methods
When you want to add one tag to your test methods, you can use one of these three
options:
First, if you want to add a tag to all test methods found from your test class, you have
to annotate your test class with the @Tag annotation. For example, let’s assume that
you want to add the tag 'A' to all test methods found from your test class.
After you have made the required changes to your test class, it looks as follows:
import org.junit.jupiter.api.Tag;
@Tag("A")
class RootClassTagAExampleTest {
}
Second, if you want to add a tag to all test methods found from a nested test class,
you have to annotate your nested test class with the @Tag annotation. For example,
let’s assume that your test class has two nested test classes and you want that:
• The test methods found from the WhenTestHasTagA class have the tag 'A'.
• The test methods found from the WhenTestHasTagB class have the tag 'B'.
After you have the made required changes to your test class, it looks as follows:
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Tag;
class NestedClassTagExampleTest {
@Nested
@DisplayName("When the test has the tag: A")
@Tag("A")
class WhenTestHasTagA {
}
@Nested
@DisplayName("When the test has the tag: B")
@Tag("B")
class WhenTestHasTagB {
}
}
6
Third, if you want to add a tag to one test method, you have to annotate your test
method with the @Tag annotation. For example, let’s assume that your test class has
two test methods and you want add different tags ('A' and 'B') to these test methods.
After you have made the required changes to your test class, its source code looks as
follows:
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
class RootClassMethodTagExampleTest {
@Test
@DisplayName("Should have the tag: A")
@Tag("A")
void shouldHaveTagA() {
}
@Test
@DisplayName("Should have the tag: B")
@Tag("B")
void shouldHaveTagB() {
}
}
Let’s move on and find out how you can add multiple tags to your test methods.
7
Adding Multiple Tags to Your Test Methods
If you want to add multiple tags to your test methods, you can use one of these two
options:
First, because the @Tag annotation is a repeatable annotation, you can simple apply
multiple @Tag annotations to your test class, nested test class, or test method. For
example, let’s assume that you want to add the tags 'A' and 'B' to all test methods
found from your test class.
After you have made the required changes to your test class, its source code looks as
follows:
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
@Tag("A")
@Tag("B")
class RootClassMultipleTagsExampleTest {
}
Second, you can annotate your test class, nested test class, or test method with the
@Tags annotation and configure the tags by setting the value of the @Tags annotation’s
value attribute. For example, let’s assume that you want to add the tags 'A' and 'B' to
all test methods found from your test class.
After you have made the required changes to your test class, its source code looks as
follows:
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Tags;
import org.junit.jupiter.api.Test;
@Tags({
@Tag("A"),
@Tag("B")
})
class RootClassMultipleTagsExampleTest {
}
8
Additional Reading:
• The Javadoc of the @Tags annotation
Next, you will find out how you can make your tests easier to write and maintain when
you are adding tags to your test methods.
9
Writing a Custom Annotation
When you add tags to your test methods, you must specify the names of your tags by
using string literals. Because it’s very like that you want to add the same tag to test
methods which are found from different test classes, you must write the same name
multiple times. This is a problem because:
• You have to remember the correct spelling of your tag’s name and double-check
that the name of your tag doesn’t contain any typos. This makes your tests hard to
write.
• If you want to change the name of your tag, you have to make that change to every
test class which contains the updated tag. This makes your tests hard to maintain.
It’s clear that you should remove duplicate tag names from your test suite. You can get
rid of duplicate tag names by writing a custom annotation which adds the required tag
to your test methods.
You can also declare constants which contain your tag names and use
these constants together with the @Tag annotation. However, I think that
using custom annotations is a better choice because they make your
test code a bit easier to read.
Let’s assume that you want to write a custom annotation which adds the tag 'unitTest'
to your test methods. You can write this annotation by following these steps:
After you have written your custom annotation, its source code looks as follows:
10
import org.junit.jupiter.api.Tag;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
You can now add the tag 'unitTest' to your test methods by annotating your test
classes and test methods with the @UnitTest annotation. For example, let’s assume
that you want to add the tag 'unitTest' to all test methods found from your test class.
After you have made the required changes to your test class, its source code looks as
follows:
@UnitTest
class UnitTestAnnotationExampleTest {
}
As you can see, if you replace the @Tag annotation with a custom annotation, you will
make your life easier because:
• You don’t have to remember the correct spelling of your tag’s name and you cannot
make any typos when you add this tag to your test methods.
• If you want to change the name of your tag, you have to make that change to only
one place.
You can now divide your test methods into groups by using JUnit 5 tags. Let’s move
on and find out how can select the invoked test methods by using tag expressions.
11
Introduction to Tag Expressions
Tag expressions are boolean expressions which allow you to specify the test methods
which are run when you run your tests. When you specify tag expressions, you can
combine tag names with the following operators:
Let’s take a look at some examples which demonstrate how you can use tag
expressions for selecting the invoked test methods.
First, if you want to run all tests which have the tag 'A', you have to use a tag
expression that looks as follows:
Second, if you want to run all tests which have the tag 'A' or the tag 'B', you have to use
a tag expression that looks as follows:
A | B
Third, if you want to run all tests which have the tag 'A' and the tag 'B', you have to use
a tag expression that looks as follows:
A & B
Fourth, if you want to run all tests which have the tag 'A' and don’t have the tag 'B', you
have to use a tag expression that looks as follows:
A & !B
12
Fifth, if you want to run all tests which have the tag 'unitTest' or the tag
'integrationTest' and have the tag 'A' or the tag 'B', you have to use a tag expression
that looks as follows:
Additional Reading:
• JUnit 5 User Guide: 4.6.2. Tag Expressions
13
Filtering Tests With Maven
When you are running your tests by using either the Maven Surefire or the Maven
Failsafe plugin and you want to configure the test methods which are run when you
run your tests, you can use these two configuration options:
• The groups configuration option allows you to configure the tag expression which
specifies the test methods which are run when you run your tests.
• The excludedGroups configuration option allows you to configure the tag
expression which specifies the test methods which aren’t run when you run your
tests.
Let’s take a look at some examples which demonstrate how you can use these
configuration options.
First, let’s assume that you want to run all tests which have the tag 'A'. After you have
made the required changes to the configuration of the Maven Surefire plugin, its
configuration looks as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<groups>A</groups>
</configuration>
</plugin>
Second, let’s assume that you want to run all tests which have the tags 'A' and 'B'.
After you have made the required changes to the configuration of the Maven Surefire
plugin, its configuration looks as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<groups>A & B</groups>
</configuration>
</plugin>
14
If you want to use the ampersand character ('&') in an XML document, you must
use a CDATA section or use the entity &.
Third, let’s assume that you want to run all tests which have the tag 'A' or the tag 'B'
and don’t have the tag 'integrationTest'. After you have made the required changes to
the configuration of the Maven Surefire plugin, its configuration looks as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<groups>A | B</groups>
<excludedGroups>integrationTest</excludedGroups>
</configuration>
</plugin>
On the other hand, if you don’t want to use two different configuration options, you can
remove the excludedGroups configuration option and use a tag expression that
excludes test methods which have the tag 'integrationTest'. After you have made the
required changes to the configuration of the Maven Surefire plugin, its configuration
looks as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<groups>(A | B) & !integrationTest</groups>
</configuration>
</plugin>
Additional Reading:
Let’s move on and find out how you can filter tests with Gradle.
15
Filtering Tests With Gradle
When you are running your tests with Gradle and you want to configure the test
methods which are run when you run your tests, you have to change the configuration
of the `Test task which runs your tests. To be more specific, you can use these two
configuration options:
• The includeTags configuration option allows you to configure the tag expression
which specifies the test methods which are run when you run your tests.
• The excludeTags configuration option allows you to configure the tag expression
which specifies the test methods which aren’t run when you run your tests.
Let’s take a look at some examples which demonstrate how you can use these
configuration options.
First, let’s assume that you want to run all tests which have the tag 'A'. After you have
made the required changes to the configuration of the Test task, its configuration
looks as follows:
test {
useJUnitPlatform {
includeTags 'A'
}
}
Second, let’s assume that you want to run all tests which have the tags 'A' and 'B'.
After you have made the required changes to the configuration of the Test task, its
configuration looks as follows:
test {
useJUnitPlatform {
includeTags 'A & B'
}
}
Third, let’s assume that you want to run all tests which have the tag 'A' or the tag 'B'
and don’t have the tag 'integrationTest'. After you have made the required changes to
the configuration of the Test task, its configuration looks as follows:
16
test {
useJUnitPlatform {
includeTags 'A | B'
excludeTags 'integrationTest'
}
}
On the other hand, if you don’t want to use two different configuration options, you can
remove the excludeTags configuration option and use a tag expression that excludes
test methods which have the tag 'integrationTest'. After you have made the required
changes to the configuration of the Test task, its configuration looks as follows:
test {
useJUnitPlatform {
includeTags '(A | B) & !integrationTest'
}
}
Additional Reading:
• Gradle User Manual: Testing in Java & JVM projects – Test Grouping
You can now add tags to your test methods and filter your test methods with Maven
and Gradle. Let’s summarize what you learned from this ebook.
17
Summary
• JUnit 5 tags allow you to divide your test methods into different groups and
configure the groups whose tests are run when you run your tests.
• If you want to add one tag to your test methods, you have to annotate your test
class, nested test class, or test method with the @Tag annotation.
• If you want to add multiple tags to your test methods, you have to annotate your
test class, nested test class, or test method with the @Tags annotation or apply
multiple @Tag annotations to your test class, nested test class, or test method.
• Tag expressions are boolean expressions which allow you to specify the test
methods which are run when you run your tests. When you want to create a new tag
expression, you have to combine tag names with logical operators.
• If you are using Maven, you can include and exclude test methods by using the
groups and excludedGroups configuration options.
• If you are using Gradle, you can include and exclude test methods by using the
includeTags and excludeTags configuration options.
18