We can use JUnit 5 test suites to run tests spread into multiple test classes and different packages.
JUnit 5 provides out of box two annotations: @SelectPackages and @SelectClasses to create test suites.
Additionally, we may use other annotations for filtering test packages, classes, or even test methods.
Create Test Suite with @SelectPackages
We can use @SelectPackages annotation to specify the names of packages to select when running a test suite via @RunWith(JUnitPlatform.class).
Specify Single Package
We have to pass “package_name” as a parameter to @SelectPackages annotation.
1 2 3 4 5 |
@RunWith(JUnitPlatform.class) @SelectPackages("com.kkjavatutorials.package1") public class JUnit5TestSuiteExample { } |
Specify Multiple Packages
We have to pass package names in the parameter as a string array (inside curly braces {}) to @SelectPackages annotation.
1 2 3 4 5 6 |
@RunWith(JUnitPlatform.class) @SelectPackages({"com.kkjavatutorials.package1","com.kkjavatutorials.package2"}) public class JUnit5TestSuiteExample { } |
Point to be noted here that if we pass ‘packageA’ in @SelectPackages annotation, then test classes present in this package AND all its sub-packages will be selected for the test suite.
Create Test Suite with @SelectClasses
We can use @SelectClasses annotation to specify the classes to select when running a test suite via @RunWith(JUnitPlatform.class).
Specify Single Class
Pass ClassName.class as parameter to @SelectClasses annotation.
1 2 3 4 5 |
@RunWith(JUnitPlatform.class) @SelectClasses( MyUtilsTest.class ) public class JUnit5TestSuiteExample { } |
Specify Multiple Classes
We can pass multiple class names in the parameter as array (inside curly braces {}) to @SelectClasses annotation.
1 2 3 4 5 |
@RunWith(JUnitPlatform.class) @SelectClasses( { ClassXTest.class, ClassYTest.class, ClassZTest.class } ) public class JUnit5TestSuiteExample { } |
@IncludePackages and @ExcludePackages
As we discussed above that @SelectPackages causes all it’s sub-packages as well to be scanned for test classes. If we want to include/exclude any specific package or sub-package then we may use @IncludePackages and @ExcludePackages annotations.
@IncludePackages Example
1 2 3 4 5 6 |
@RunWith(JUnitPlatform.class) @SelectPackages("com.kkjavatutorials.packageA") @IncludePackages("com.kkjavatutorials.packageA.packageC") public class JUnit5TestSuiteExample { } |
This will add tests from test classes in com.kkjavatutorials.packageA.packageC only i.e. ClassCTest.
@ExcludePackages Example
1 2 3 4 5 6 |
@RunWith(JUnitPlatform.class) @SelectPackages("com.kkjavatutorials.packageA") @ExcludePackages("com.kkjavatutorials.packageA.packageC") public class JUnit5TestSuiteExample { } |
This will add tests from test classes in com.kkjavatutorials.packageA but exclude all test classes from sub-package com.kkjavatutorials.packageA.packageC i.e. ClassXTest and ClassYTest.
@IncludeClassNamePatterns and @ExcludeClassNamePatterns
Sometimes, it is not feasible to include all packages or test class names in select annotations. In that case, we may give a broader package scope and apply filtering on which test classes to be included or excluded from the suite.
To specify test class names patterns to exclude or include, you can use @IncludeClassNamePatterns and @ExcludeClassNamePatterns annotations.
@IncludeClassNamePatterns Example
Include all test classes with names ending with XTest or XTests.
1 2 3 4 5 6 |
@RunWith(JUnitPlatform.class) @SelectPackages("com.kkjavatutorials.packageA") @IncludeClassNamePatterns({"^.*XTests?$"}) public class JUnit5TestSuiteExample { } |
@ExcludeClassNamePatterns Example
Exclude all test classes with name ending with XTest or XTests.
1 2 3 4 5 6 |
@RunWith(JUnitPlatform.class) @SelectPackages("com.kkjavatutorials.packageA") @ExcludeClassNamePatterns({"^.*XTests?$"}) public class JUnit5TestSuiteExample { } |
We may apply more than one pattern in above annotations. In case of multiple pattern match, they are combined using OR semantics. It means that if fully qualified name of a class matches against at least one of the patterns, the class will be excluded/included from the test suite.
@IncludeTags and @ExcludeTags
In enterprise applications, we may have tagged test cases which we want to run in specific environments e.g. dev or prod. we can include or exclude tests based on these tags as well, from a test suite.
@IncludeTags Example
This test suite will run all tests tagged with prod inside package com.kkjavatutorials.packageA (and it’s sub-packages).
1 2 3 4 5 6 |
@RunWith(JUnitPlatform.class) @SelectPackages("com.kkjavatutorials.packageA") @IncludeTags("prod") public class JUnit5TestSuiteExample { } |
@ExcludeTags Example
This test suite will exclude all tests tagged with dev inside package com.kkjavatutorials.packageA (and it’s sub-packages).
1 2 3 4 5 6 |
@RunWith(JUnitPlatform.class) @SelectPackages("com.kkjavatutorials.packageA") @ExcludeTags("dev") public class JUnit5TestSuiteExample { } |
Now it is very clear that there are multiple ways to create test suites in JUnit 5 and it has very strong support for filtering tests to/from test suites.
Let’s try to understand the above concept using a demo project
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kkjavatutorials</groupId> <artifactId>JUnit5TestSuiteExample</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.target>8</maven.compiler.target> <maven.compiler.source>8</maven.compiler.source> <junit.jupiter.version>5.6.2</junit.jupiter.version> <junit.platform.version>1.6.2</junit.platform.version> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.jupiter.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.jupiter.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-runner</artifactId> <version>${junit.platform.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> </plugins> </build> </project> |
MyUtils.java
1 2 3 4 5 6 7 8 |
package com.kkjavatutorials; public class MyUtils { public int add(int n1, int n2) { return n1+n2; } } |
MyUtilsTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package com.kkjavatutorials; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @DisplayName(value = "All the Test Cases of MyUtils") public class MyUtilsTest { private static MyUtils myUtils; @BeforeAll static void setUp() { myUtils = new MyUtils(); System.out.println("Test data set up is done.."); } @BeforeEach void beforeEach() { System.out.println("@BeforeEach is executed.."); } @Test @Tag(value = "dev") @DisplayName(value = "adding two positive numbers") void test_add_two_positive_numbers() { int actualResult = myUtils.add(20, 10); assertEquals(30, actualResult); } @Test @Tag(value = "dev") @DisplayName(value = "adding two negtaive numbers") void test_add_two_negative_numbers() { int actualResult = myUtils.add(-20, -10); assertEquals(-30, actualResult); } @Test @DisplayName(value = "adding one positive and one negtaive number") void test_add_one_positive_and_one_negative_number() { int actualResult = myUtils.add(20, -10); assertEquals(10, actualResult); } @AfterEach void afterEach() { System.out.println("@AfterEach is executed.."); } @AfterAll static void tearDown() { myUtils = null; System.out.println("Test data teardown is done.."); } } |
TestingAStack.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
package com.kkjavatutorials.packageA; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.EmptyStackException; import java.util.Stack; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; /** * Nested Tests JUnit 5 Example * @author KK JavaTutorials */ @DisplayName("A Stack") public class TestingAStack { private Stack<String> stack; @Test @DisplayName("is instantiated with new Stack()") void isInstantiatedWithNew() { stack = new Stack<String>(); } @Nested @DisplayName("when new") @Tag(value = "dev") class WhenNew { @BeforeEach void createNewStack() { stack = new Stack<>(); } @Test @DisplayName("is empty") void isEmpty() { assertTrue(stack.isEmpty()); } @Test @DisplayName("throws EmptyStackException when popped") void throwsExceptionWhenPopped() { assertThrows(EmptyStackException.class, stack::pop); } @Test @DisplayName("throws EmptyStackException when peeked") void throwsExceptionWhenPeeked() { assertThrows(EmptyStackException.class, stack::peek); } @Nested @DisplayName("after pushing an element") class AfterPushing { String element = "KK JavaTutorials"; @BeforeEach void pushAnElement() { stack.push(element); } @Test @DisplayName("it is no longer empty") void isNotEmpty() { assertFalse(stack.isEmpty()); } @Test @DisplayName("returns the element when popped and is empty") void returnElementWhenPopped() { assertEquals(element, stack.pop()); assertTrue(stack.isEmpty()); } @Test @DisplayName("returns the peek element but remains not empty") void returnElementWhenPeeked() { assertEquals(element, stack.peek()); assertFalse(stack.isEmpty()); } } } } |
TestSuiteWithExcludePackagesExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kkjavatutorials.runner; import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.ExcludePackages; import org.junit.platform.suite.api.SelectPackages; import org.junit.runner.RunWith; /** *@SelectPackages and @ExcludePackages demo * @author KK JavaTutorials * */ @RunWith(JUnitPlatform.class) @SelectPackages(value = { "com.kkjavatutorials"}) @ExcludePackages(value = {"com.kkjavatutorials.packageA"}) public class TestSuiteWithExcludePackagesExample { } |
TestSuiteWithIncludePackagesExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kkjavatutorials.runner; import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.IncludePackages; import org.junit.platform.suite.api.SelectPackages; import org.junit.runner.RunWith; /** * @SelectPackages and @IncludePackages demo * @author KK JavaTutorials * */ @RunWith(JUnitPlatform.class) @SelectPackages(value = { "com.kkjavatutorials"}) @IncludePackages(value = {"com.kkjavatutorials.packageA"}) public class TestSuiteWithIncludePackagesExample { } |
TestSuiteWithIncludeTagsExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.kkjavatutorials.runner; import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.SelectPackages; import org.junit.runner.RunWith; /** * @SelectPackages,@IncludeTags and @ExcludeTags demo * @author KK JavaTutorials * */ @RunWith(JUnitPlatform.class) @SelectPackages(value = { "com.kkjavatutorials"}) //@IncludeTags("dev") @ExcludeTags("dev") public class TestSuiteWithIncludeTagsExample { } |
TestSuiteWithSelectPackagesAndClassesExample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.kkjavatutorials.runner; 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; import com.kkjavatutorials.MyUtilsTest; import com.kkjavatutorials.packageA.TestingAStack; /** * @SelectPackages and @SelectClasses demo * @author KK JavaTutorials * */ @RunWith(JUnitPlatform.class) //@SelectPackages(value = { "com.kkjavatutorials","com.kkjavatutorials.packageA" }) @SelectClasses( { MyUtilsTest.class, TestingAStack.class} ) public class TestSuiteWithSelectPackagesAndClassesExample { } |
The output of the above project:
You May Also Like:
Junit 5 Architecture
JUnit 5 Annotations
JUnit 5 Maven Dependency
JUnit 5 with Gradle Dependency
JUnit 5 Test Lifecycle
JUnit 5 @BeforeAll annotation example
Unit 5 @AfterAll annotation example
JUnit 5 @BeforeEach and @AfterEach annotation Example
JUnit 5 Display Names
Assertions in JUnit 5 Examples
Third-party Assertion Libraries support in JUnit 5
JUnit 5 Assumptions Examples
Conditional Test Execution in JUnit 5
JUnit 5 Nested Tests Example
JUnit 5 @Tag Annotation example
Test Execution Order in Junit 5
Dependency Injection and Testing in JUnit 5
Test Interfaces and Default Methods in JUnit 5
That’s all about JUnit 5 Test Suites Examples
If you have any feedback or suggestion please feel free to drop in below comment box.