Getting started with JUnit 5 TestSuite

JUnit 5 Test Suites allow developers to aggregate and execute multiple test classes, packages, or tagged test cases in a single test run. While legacy JUnit 4 relied on @RunWith(JUnitPlatform.class), modern JUnit 5 (version 5.8+) utilizes the dedicated @Suite annotation alongside @SelectClasses and @SelectPackages from the junit-platform-suite engine. In this guide, you will learn how to configure and run modern JUnit 5 test suites in Maven and Gradle builds.

How to declare a JUnit 5 Test Suite

Firstly, if you are new to JUnit, we recommend checking this article: JUnit 5 : Step-by-step Tutorial

A JUnit 5 TestSuite enables to run multiple tests together. To aggregate multiple Tests in a TestSuite you can use the following annotations:

  • @SelectPackages – specifies the names of packages for the test suite
  • @SelectClasses – specifies the classes for the test suite. They can be located in different packages.

Here is an example TestSuite which uses both annotation to select two Test Classes and a package:

import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.runner.RunWith;


@RunWith(JUnitPlatform.class)
@SelectClasses( { Math1Test.class, Math2Test.class } )
@SelectPackages("com.example.project")
public class TestSuiteDemo {
}

Coding the Test Classes

Next, let’s code the two Java Classes Math1Test and Math2Test which are part of our Test Suite. Let’s begin with Math1Test:

package com.example.project;

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

public class Math1Test {

    @Test
    public void testAddition() {
        int result = Calculator.add(3, 7);
        Assertions.assertEquals(10, result, "3 + 7 should equal 10");
    }

    @Test
    public void testSubtraction() {
        int result = Calculator.subtract(10, 4);
        Assertions.assertEquals(6, result, "10 - 4 should equal 6");
    }
}

Then, here is Math2Test Class:

package com.example.project;

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

public class Math2Test {

    @Test
    public void testMultiplication() {
        int result = Calculator.multiply(5, 6);
        Assertions.assertEquals(30, result, "5 * 6 should equal 30");
    }

    @Test
    public void testDivision() {
        double result = Calculator.divide(20, 5);
        Assertions.assertEquals(4.0, result, "20 / 5 should equal 4.0");
    }
}

As you can see, both Test Classes are Testing the Calculator Class which contains all the four basic arithmetic operations:

package com.example.project;
 

public class Calculator {

    public static int add(int a, int b) {
        return a + b;
    }

    public static int subtract(int a, int b) {
        return a - b;
    }

    public static int multiply(int a, int b) {
        return a * b;
    }

    public static double divide(double a, double b) {
        if (b == 0) {
            throw new IllegalArgumentException("Cannot divide by zero");
        }
        return a / b;
    }
}

Building the Test Suite:

In order to build the project, make sure you include the JUnit 5 BOM File and, besides the Engine and the API, include also the PlatFormRunner which is essential for the JUnit TestSuite:

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.junit</groupId>
			<artifactId>junit-bom</artifactId>
			<version>5.10.1</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>
<dependencies>
	<dependency>
		<groupId>org.junit.platform</groupId>
		<artifactId>junit-platform-runner</artifactId>
	</dependency>
	<dependency>
		<groupId>org.junit.jupiter</groupId>
		<artifactId>junit-jupiter-engine</artifactId>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.junit.jupiter</groupId>
		<artifactId>junit-jupiter-api</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

Here is the Project View of our TestSuite:

JUnit 5 Test Suite Example tutorial

Running the TestSuite

Switch to the Test perspective of your IDE and execute the TestSuiteDemo Class:

JUnit 5 TestSuite step-by-step guide

As you can see, the execution of the TestSuiteDemo Class triggered the execution of both Math1Test and Math2Test.

Creating Dynamic Tests with the @TestFactory Annotation

JUnit 5 dynamic tests allow you to declare and execute test cases generated at runtime. Unlike static tests, which define a fixed number of test cases at compile time, dynamic tests enable dynamically defining test cases at runtime.

Dynamic tests can be generated by a method annotated with @TestFactory:

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

public class DynamicTestSuite {

    @TestFactory
    public TestSuite dynamicTestSuite() {
        return TestSuite.create("Dynamic Test Suite")
                .includePackages("com.example.project")
                .selectClass(MathTest.class)
                .selectClass(MathTest2.class)
                .build();
    }
}

Conclusion:

JUnit 5 Test Suites provide a flexible and powerful way to organize and execute tests in your Java projects. Leveraging advanced features such as conditional execution, test ordering, tags, and parameterized tests enhances the efficiency and readability of test suites.

Source code: https://github.com/fmarchioni/mastertheboss/tree/master/test/junit5-testsuite

Modernizing Legacy JUnit 5 Test Suites

Legacy JUnit 5 tutorials often recommended using @RunWith(JUnitPlatform.class) from JUnit 4 runner bridges. In modern JUnit 5 (5.8 and newer), you should use the standalone @Suite platform annotations instead:

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectPackages("com.example.project")
@SelectClasses({ Math1Test.class, Math2Test.class })
public class ModernTestSuite {
}

To support @Suite, ensure you include org.junit.platform:junit-platform-suite-engine in your pom.xml test dependencies.


Recommended Articles

Mastering Test Tagging in JUnit 5: Filtering and Executing Tests with Ease

Learn how to tag tests in JUnit 5 using annotations like @Tag. Discover two ways to filter test execution: Maven-Surefire plugin configuration and custom TestSuite class usage.

Create a JUnit 5 Project with IntelliJ IDEA - Step-by-Step Guide

Learn how to create a simple JUnit 5 project using IntelliJ IDEA. Follow our step-by-step guide to set up your Maven project, add a basic class and test it using JUnit.

Unlock JUnit 5 Test Execution in Maven Projects - A Comprehensive Guide

Ensure your JUnit 5 tests run smoothly with this comprehensive guide to resolving common issues.

How to Assert No Exception Thrown in Java with JUnit 4 and JUnit 5

Learn how to assert no exception thrown in Java tests using JUnit 4 and JUnit 5. #Java #JUnit #Testing #CloudNative