How do I use tags to group JUnit tests?
In JUnit 5, you can use the @Tag annotation to group tests into categories such as: fast slow unit integration database api smoke Tags are useful when you want to run only certain groups of tests, for example only fast unit tests during development, or only integration tests in a CI pipeline. 1. Basic Example […]
Artikel oleh Wayan · Sumber: Kode Java ↗
Terjemahan artikel ini belum tersedia. Isi asli ditampilkan.
In JUnit 5, you can use the @Tag annotation to group tests into categories such as:
fastslowunitintegrationdatabaseapismoke
Tags are useful when you want to run only certain groups of tests, for example only fast unit tests during development, or only integration tests in a CI pipeline.
1. Basic Example
Use @Tag on a test method:
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CalculatorTest {
@Test
@Tag("fast")
void shouldAddTwoNumbers() {
Calculator calculator = new Calculator();
int result = calculator.add(2, 3);
assertEquals(5, result);
}
@Test
@Tag("slow")
void shouldCalculateLargeDataSet() {
Calculator calculator = new Calculator();
int result = calculator.processLargeDataSet();
assertEquals(1000, result);
}
}
In this example:
shouldAddTwoNumbers()belongs to thefastgroup.shouldCalculateLargeDataSet()belongs to theslowgroup.
2. Tag an Entire Test Class
You can place @Tag on a class to apply the tag to all tests inside it.
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Tag("unit")
class StringUtilsTest {
@Test
void shouldReturnTrueForBlankString() {
assertTrue(StringUtils.isBlank(""));
}
@Test
void shouldReturnTrueForWhitespaceString() {
assertTrue(StringUtils.isBlank(" "));
}
}
All tests in StringUtilsTest are now tagged as unit.
3. Use Multiple Tags
A test can have more than one tag.
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class UserServiceTest {
@Test
@Tag("unit")
@Tag("fast")
void shouldCreateUser() {
UserService userService = new UserService();
User user = userService.createUser("alice@example.com");
assertNotNull(user);
}
@Test
@Tag("integration")
@Tag("database")
void shouldSaveUserToDatabase() {
UserRepository userRepository = new UserRepository();
User user = userRepository.save(new User("bob@example.com"));
assertNotNull(user.getId());
}
}
This allows you to run tests by different categories.
For example:
- Run all
unittests. - Run all
fasttests. - Run all
integrationtests. - Exclude all
databasetests.
4. Run Tagged Tests with Maven
If you are using Maven Surefire, you can run tests with a specific tag like this:
mvn test -Dgroups=unit
To run multiple tags:
mvn test -Dgroups=unit,fast
To exclude a tag:
mvn test -DexcludedGroups=slow
Example:
mvn test -Dgroups=integration -DexcludedGroups=slow
This runs tests tagged with integration, but excludes tests tagged with slow.
5. Configure Tags in pom.xml
You can also configure Maven to include or exclude tags permanently.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
<configuration>
<groups>unit</groups>
<excludedGroups>slow</excludedGroups>
</configuration>
</plugin>
</plugins>
</build>
This configuration runs tests tagged unit and excludes tests tagged slow.
6. Run Tagged Tests with Gradle
If you are using Gradle, configure the test task:
test {
useJUnitPlatform {
includeTags 'unit'
excludeTags 'slow'
}
}
Then run:
gradle test
You can also create separate test tasks:
tasks.register('integrationTest', Test) {
useJUnitPlatform {
includeTags 'integration'
}
}
Run it with:
gradle integrationTest
7. Tag Integration Tests
A common use case is separating unit tests from integration tests.
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Tag("integration")
class UserRepositoryTest {
@Test
void shouldConnectToDatabase() {
boolean connected = true;
assertTrue(connected);
}
}
Then you can run only integration tests:
mvn test -Dgroups=integration
Or exclude them during regular builds:
mvn test -DexcludedGroups=integration
8. Tag Nested Tests
Tags also work with nested test classes.
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
class OrderServiceTest {
@Nested
@Tag("validation")
class ValidationTests {
@Test
void shouldRejectInvalidOrder() {
// validation test
}
@Test
void shouldAcceptValidOrder() {
// validation test
}
}
@Nested
@Tag("pricing")
class PricingTests {
@Test
void shouldCalculateDiscount() {
// pricing test
}
@Test
void shouldApplyTax() {
// pricing test
}
}
}
Here:
- All tests in
ValidationTestsare taggedvalidation. - All tests in
PricingTestsare taggedpricing.
9. Tag Naming Rules
JUnit tag names must follow a few rules:
- A tag must not be blank.
- A tag must not contain whitespace.
- A tag must not contain ISO control characters.
- A tag must not contain reserved characters:
,()&|!
Good examples:
@Tag("unit")
@Tag("integration")
@Tag("fast")
@Tag("database")
@Tag("smoke")
Avoid:
@Tag("unit test")
@Tag("fast,unit")
@Tag("integration&database")
10. Best Practices
Use tags for broad execution groups, not for every small detail.
Good tag categories:
unitintegrationslowfastdatabaseapismoke
Avoid over-tagging tests with too many labels.
For example, this is usually enough:
@Test
@Tag("integration")
@Tag("database")
void shouldSaveCustomer() {
}
But this is probably too much:
@Test
@Tag("integration")
@Tag("database")
@Tag("repository")
@Tag("customer")
@Tag("save")
@Tag("positive")
void shouldSaveCustomer() {
}
Summary
Use JUnit 5 @Tag to group and filter tests.
@Test
@Tag("fast")
void shouldRunQuickly() {
}
You can apply tags to:
- Individual test methods
- Entire test classes
- Nested test classes
Then run selected groups using Maven or Gradle:
mvn test -Dgroups=fast
test {
useJUnitPlatform {
includeTags 'fast'
}
}
Tags are especially useful for separating unit tests, integration tests, slow tests, and database-dependent tests.
