### Generate Antora Site with Gradle Source: https://github.com/junit-team/junit-framework/blob/main/documentation/README.md Use this command to generate the HTML version of the User Guide. Ensure the 'graphviz' package is installed on Linux systems for PlantUML image generation. ```bash ./gradlew antora ``` -------------------------------- ### Example Custom Arguments Provider Implementation Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc An example of a custom `ArgumentsProvider` implementation. This demonstrates how to define a reusable source for test arguments. ```java include::example$java/example/ParameterizedTestDemo.java[tags=ArgumentsProvider_example] ``` -------------------------------- ### Install Local JUnit Gradle Snapshot Source: https://github.com/junit-team/junit-framework/wiki/Testing-Gradle-Plugin-Before-Pushing-to-GitHub Builds and installs the junit-gradle snapshot JAR into your local Maven repository. This is the first step to testing local plugin changes. ```bash $> gradle clean install ``` -------------------------------- ### Simple Method Source Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc Demonstrates a simple factory method returning a Stream of arguments for a single-parameter test. ```java import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; class ParameterizedTestDemo { @ParameterizedTest @MethodSource("streamOfStrings") void simple_MethodSource_example(String argument) { // ... } static Stream streamOfStrings() { return Stream.of("apple", "banana"); } } ``` -------------------------------- ### Standard Test Class Example (Kotlin) Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/test-classes-and-methods.adoc Demonstrates the use of @Test methods and all supported lifecycle methods in a standard Kotlin test class. This example is tagged for user guide inclusion. ```kotlin include::example$kotlin/example/StandardTests.kt[tags=user_guide] ``` -------------------------------- ### Install JUnit Modules to Maven Local Source: https://github.com/junit-team/junit-framework/blob/main/README.md Execute this command to install all built modules into your local Maven repository, making them available for other local projects. Requires JDK 25 and the Gradle Wrapper. ```bash ./gradlew publishToMavenLocal ``` -------------------------------- ### Standard Test Class Example (Java) Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/test-classes-and-methods.adoc Demonstrates the use of @Test methods and all supported lifecycle methods in a standard Java test class. This example is tagged for user guide inclusion. ```java include::example$java/example/StandardTests.java[tags=user_guide] ``` -------------------------------- ### Create a Java Test File Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/running-tests/source-launcher.adoc Create a `HelloTests.java` file with the provided content to define your tests. This example includes a `main` method to run JUnit and a test method `stringLength`. ```java import module org.junit.start; void main() { JUnit.run(); } @Test void stringLength() { Assertions.assertEquals(11, "Hello JUnit".length()); } ``` -------------------------------- ### Multi-Argument Method Source Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc Demonstrates how to provide multiple arguments per test invocation by returning a Stream of Arguments instances or object arrays. ```java import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; class ParameterizedTestDemo { @ParameterizedTest @MethodSource("multiArgMethodSource") void multi_arg_MethodSource_example(int arg1, String arg2, Object arg3) { // ... } static Stream multiArgMethodSource() { return Stream.of( Arguments.of(1, "apple", "a"), Arguments.of(2, "banana", "b"), Arguments.of(3, "cherry", "c") ); } } ``` -------------------------------- ### Example Project Layout for Modular Application Source: https://github.com/junit-team/junit-framework/wiki/Testing-with-Jigsaw Illustrates the directory structure for a modular Java application, including main and test sources for different modules and integration tests. ```plaintext application/ src/ main/ application.api/ foo/ bar/ api/ ApplicationVersion.java ApplicationInterface.java module-info.java = module application.api { requires ...; exports foo.bar.application.api; } application.core/ application.gui/ application.main/ test/ application.api/ foo/ bar/ api/ ApplicationVersionTests.java ApplicationInterfaceTests.java module-info.java = module application.api { requires ...; requires junit.api; exports foo.bar.application.api; } application.core/ application.gui/ application.main/ integration.api/ tests/ ApplicationApiTests.java module-info.java = module integration.api { requires application.api; requires junit.api; } integration.main/ tests/ ApplicationMainTests.java module-info.java = module integration.main { requires application.main; requires junit.api; } ``` -------------------------------- ### AssertJ Integration Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/assertions.adoc Shows how to use AssertJ's assertThat() for fluent assertions within a JUnit Jupiter test. Ensure AssertJ is on the classpath. ```java import static org.assertj.core.api.Assertions.*; import org.junit.jupiter.api.Test; class AssertJAssertionsDemo { @Test void assertWithAssertJ() { assertThat("test") .as("The optional message is now the last argument.") .startsWith("test") .contains("es"); } } ``` -------------------------------- ### Primitive Stream Method Source Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc Illustrates the support for primitive streams like IntStream as a return type for factory methods. ```java import java.util.stream.IntStream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; class ParameterizedTestDemo { @ParameterizedTest @MethodSource("range") void primitive_MethodSource_example(int argument) { // ... } static IntStream range() { return IntStream.range(0, 20); } } ``` -------------------------------- ### External Static Method Source Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc Shows how to reference a static factory method from an external class using its fully qualified name. ```java package example; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; class ExternalMethodSourceDemo { @ParameterizedTest @MethodSource("example.MyTestProvider#provideStringsForExternalMethodSource") void external_MethodSource_example(String argument) { // ... } } ``` -------------------------------- ### Dynamic Tests Demo - Kotlin Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/dynamic-tests.adoc Demonstrates generating dynamic tests in Kotlin using @TestFactory. Shows examples of returning collections, streams, and using DynamicTest.stream() for creating tests. ```kotlin import org.junit.jupiter.api.DynamicContainer.dynamicContainer import org.junit.jupiter.api.DynamicTest.dynamicTest import org.junit.jupiter.api.TestFactory import org.junit.jupiter.api.DynamicNode import java.util.stream.Stream import java.util.stream.IntStream class DynamicTestsDemo { @TestFactory fun dynamicTestsFromStream(): Stream { return Stream.of("level 1", "level 2", "level 3") .map { name -> dynamicTest("Test for $name") { println("Running test for: $name") } } } @TestFactory fun dynamicTestsFromCollection(): Collection { return listOf( dynamicTest("simple test 1") { assertTrue(true) }, dynamicTest("simple test 2") { assertEquals(1, 1) } ) } @TestFactory fun dynamicTestsFromIterator(): Iterator { return listOf( dynamicTest("iterator test 1") { assertTrue(true) }, dynamicTest("iterator test 2") { assertEquals(1, 1) } ).iterator() } @TestFactory fun dynamicTestsFromIntStream(): Stream { return dynamicTest.stream(IntStream.of(1, 2, 3), { i -> "Test $i" }, { i -> assertEquals(i, i) }) } @TestFactory fun generateRandomNumberOfTests(): Iterator { // Random number of tests for demonstration purposes val numberOfTests = (1..10).random() return dynamicTest.stream(IntStream.rangeClosed(1, numberOfTests).iterator(), { i -> "Random test $i" }, { i -> println("Executing random test $i") }) } @TestFactory fun dynamicTestsFromStreamFactoryMethod(): Stream { return Stream.of("A", "B", "C") .flatMap { dynamicTest.stream(IntStream.rangeClosed(1, 2).iterator(), { i -> "Test $it-$i" }, { i -> println("Executing test $it-$i") }) } .limit(3) // Limit the total number of dynamic tests } @TestFactory fun dynamicNodeSingleTest(): DynamicNode { return dynamicTest("Single dynamic test") { assertEquals(4, 2 * 2) } } @TestFactory fun dynamicNodeSingleContainer(): DynamicNode { return dynamicContainer("Container with one test", listOf( dynamicTest("Test inside container") { assertTrue(true) } )) } @TestFactory fun dynamicNodeNestedContainer(): DynamicNode { return dynamicContainer("Nested container", listOf( dynamicContainer("Inner container", listOf( dynamicTest("Test in inner container") { assertTrue(true) } )), dynamicTest("Test in outer container") { assertTrue(true) } )) } // Example of an invalid return type (will cause a warning) @TestFactory fun invalidReturnType(): String { return "This is not a DynamicNode or stream of DynamicNodes" } private fun assertTrue(condition: Boolean) { if (!condition) { throw AssertionError("Assertion failed") } } private fun assertEquals(expected: Int, actual: Int) { if (expected != actual) { throw AssertionError("Expected: $expected, Actual: $actual") } } } ``` -------------------------------- ### Use Custom @JimfsTempDir Annotation Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/built-in-extensions.adoc Demonstrates the usage of the custom @JimfsTempDir annotation as a direct replacement for @TempDir with JimfsFactory. This simplifies test setup. ```java import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.assertTrue; class TempDirectoryDemo { @Test void userGuideComposedAnnotationUsage(@TempDir(factory = org.junit.jupiter.api.io.TempDirFactory.JimfsFactory.class) Path testDir) { // user_guide_composed_annotation_usage assertTrue(testDir.toFile().isDirectory()); } } ``` ```kotlin import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir import java.nio.file.Path import kotlin.test.assertTrue class TempDirectoryDemo { @Test fun userGuideComposedAnnotationUsage(@TempDir(factory = org.junit.jupiter.api.io.TempDirFactory.JimfsFactory::class) testDir: Path) { // user_guide_composed_annotation_usage assertTrue(testDir.toFile().isDirectory()) } } ``` -------------------------------- ### Kotlin IndicativeSentences Display Name Generator Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates using the IndicativeSentences display name generator in Kotlin. ```kotlin package example.kotlin.example import org.junit.jupiter.api.DisplayNameGeneration import org.junit.jupiter.api.Test import org.junit.jupiter.api.DisplayNameGenerator @DisplayNameGeneration(DisplayNameGenerator.IndicativeSentences::class) class DisplayNameGeneratorDemo { @Test fun `a year is a leap year`() { } @Test fun `if it is divisible by 4 but not by 100`() { } @Test fun `if it is one of the following years`() { } @Test fun `year 2016`() { } @Test fun `year 2020`() { } @Test fun `year 2048`() { } } ``` -------------------------------- ### AbstractDatabaseTests Lifecycle Methods Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/extensions/relative-execution-order-of-user-code-and-extensions.adoc Abstract base class defining @BeforeAll, @AfterAll, @BeforeEach, and @AfterEach methods for database interaction setup and teardown. ```java package com.example.callbacks; 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.extension.ExtendWith; import static com.example.callbacks.Logger.log; @ExtendWith({Extension1.class, Extension2.class}) public abstract class AbstractDatabaseTests { @BeforeAll static void createDatabase() { log("@BeforeAll AbstractDatabaseTests.createDatabase()", null); } @AfterAll static void destroyDatabase() { log("@AfterAll AbstractDatabaseTests.destroyDatabase()", null); } @BeforeEach void connectToDatabase() { log("@BeforeEach AbstractDatabaseTests.connectToDatabase()", null); } @AfterEach void disconnectFromDatabase() { log("@AfterEach AbstractDatabaseTests.disconnectFromDatabase()", null); } } ``` -------------------------------- ### Java IndicativeSentences Display Name Generator Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates using the IndicativeSentences display name generator in Java. ```java package example.java; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.DisplayNameGenerator; @DisplayNameGeneration(DisplayNameGenerator.IndicativeSentences.class) class DisplayNameGeneratorDemo { @Test void a_year_is_a_leap_year() { } @Test void if_it_is_divisible_by_4_but_not_by_100() { } @Test void if_it_is_one_of_the_following_years() { } @Test void year_2016() { } @Test void year_2020() { } @Test void year_2048() { } } ``` -------------------------------- ### Method Source Parameter Resolution Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc Demonstrates how factory methods can declare parameters that are resolved by JUnit Jupiter's ParameterResolver extension API. ```java import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; class MethodSourceParameterResolutionDemo { @ParameterizedTest @ArgumentsSource(MyArgumentsProvider.class) void parameter_resolution_MethodSource_example(int arg1, String arg2) { // ... } static class MyArgumentsProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) throws Exception { return Stream.of(Arguments.of(1, "test")); } } } ``` -------------------------------- ### ParameterResolver Example for Parameterized Tests Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc Demonstrates how to use ParameterResolver extensions with @ParameterizedTest methods. Ensure parameters resolved by argument sources appear first in the parameter list. ```java import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import java.util.stream.Stream; public class ParameterResolverDemo { @ParameterizedTest @ValueSource(strings = {"Hello", "World"}) void testWithParameterResolver(String message, MyParameterResolver resolver) { assertEquals(message.toUpperCase(), resolver.resolve(message)); } static class MyParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return parameterContext.getParameter().getType().equals(MyParameterResolver.class); } @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return this; } public String resolve(String message) { return message.toUpperCase(); } } } ``` -------------------------------- ### JUnit Jupiter ExtensionContext Store API: 6.0.0 Source: https://github.com/junit-team/junit-framework/wiki/Upgrading-to-JUnit-6.0 Examples of using the new `computeIfAbsent` methods on `ExtensionContext.Store` in JUnit 6.0.0. These replace the deprecated methods from JUnit 5.x. ```java store.computeIfAbsent(MyType.class); // <1> returns MyType ``` ```java store.computeIfAbsent("key", key -> new MyType()); // <2> returns Object ``` ```java store.computeIfAbsent("key", key -> new MyType(), MyType.class); // <3> returns MyType ``` -------------------------------- ### Implement TimingExtension in Java Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/extensions/test-lifecycle-callbacks.adoc This extension implements BeforeTestExecutionCallback and AfterTestExecutionCallback to time and log test execution. It requires no specific setup beyond implementing the interfaces. ```java package example.timing; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TimingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback { private static final Logger LOG = LoggerFactory.getLogger(TimingExtension.class); private static final String START_TIME = "start_time"; @Override public void beforeTestExecution(ExtensionContext context) { context.getStore().put(START_TIME, System.currentTimeMillis()); } @Override public void afterTestExecution(ExtensionContext context) { long startTime = context.getStore().remove(START_TIME, long.class); long duration = System.currentTimeMillis() - startTime; String testMethodName = context.getRequiredTestMethod().getName(); LOG.info("Method [{}] took {} ms.", testMethodName, duration); } } ``` -------------------------------- ### Kotlin Assumptions Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/assumptions.adoc Shows how to use JUnit Jupiter's assumption methods in Kotlin. Similar to Java, invalid assumptions lead to test abortion. ```kotlin import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assumptions.assumeTrue import org.junit.jupiter.api.Test internal class AssumptionsDemo { @Test fun valueIsOne() { assumeTrue(true) { "Value is not one" } assertTrue(true) { "This will be executed" } } @Test fun valueIsTwo() { assumeTrue(false) { "Value is not two" } assertTrue(true) { "This will not be executed" } } } ``` -------------------------------- ### Basic JUnit Jupiter Test Case in Java Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/intro.adoc This is a minimal example of a test case using JUnit Jupiter. Ensure you have the necessary JUnit Jupiter dependencies added to your project. ```java package example; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; class MyFirstJUnitJupiterTests { @Test void્સ myFirstTest() { assertTrue(true, "This test should pass"); } } ``` -------------------------------- ### Configure LauncherConfig with Builder API Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/advanced-topics/launcher-api.adoc Demonstrates how to create a LauncherConfig instance using the fluent builder API for fine-grained control over test engine and listener registration. ```java LauncherConfig launcherConfig = LauncherConfig.builder() .addLauncherInterceptor(new MyLauncherInterceptor()) .addTestExecutionListener(new MyTestExecutionListener()) .enable(ConfigurationParameters.forFile(Paths.get("junit-platform.properties"))) .build(); ``` -------------------------------- ### Example Test Execution Events Output Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/advanced-topics/testkit.adoc This is an example of the output generated when debugging all events from a JUnit Jupiter test execution. It shows the sequence and type of events, including STARTED, SKIPPED, FINISHED, and their associated test descriptors and results. ```text All Events: Event [type = STARTED, testDescriptor = JupiterEngineDescriptor: [engine:junit-jupiter], timestamp = 2018-12-14T12:45:14.082280Z, payload = null] Event [type = STARTED, testDescriptor = ClassTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase], timestamp = 2018-12-14T12:45:14.089339Z, payload = null] Event [type = SKIPPED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:skippedTest()], timestamp = 2018-12-14T12:45:14.094314Z, payload = 'for demonstration purposes'] Event [type = STARTED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:succeedingTest()], timestamp = 2018-12-14T12:45:14.095182Z, payload = null] Event [type = FINISHED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:succeedingTest()], timestamp = 2018-12-14T12:45:14.104922Z, payload = TestExecutionResult [status = SUCCESSFUL, throwable = null]] Event [type = STARTED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:abortedTest()], timestamp = 2018-12-14T12:45:14.106121Z, payload = null] Event [type = FINISHED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:abortedTest()], timestamp = 2018-12-14T12:45:14.109956Z, payload = TestExecutionResult [status = ABORTED, throwable = org.opentest4j.TestAbortedException: Assumption failed: abc does not contain Z]] Event [type = STARTED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:failingTest()], timestamp = 2018-12-14T12:45:14.110680Z, payload = null] Event [type = FINISHED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:failingTest()], timestamp = 2018-12-14T12:45:14.111217Z, payload = TestExecutionResult [status = FAILED, throwable = java.lang.ArithmeticException: / by zero]] Event [type = FINISHED, testDescriptor = ClassTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase], timestamp = 2018-12-14T12:45:14.113731Z, payload = TestExecutionResult [status = SUCCESSFUL, throwable = null]] Event [type = FINISHED, testDescriptor = JupiterEngineDescriptor: [engine:junit-jupiter], timestamp = 2018-12-14T12:45:14.113806Z, payload = TestExecutionResult [status = SUCCESSFUL, throwable = null]] ``` -------------------------------- ### Test Class as Java Record Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/test-classes-and-methods.adoc Illustrates how to use Java record classes as test classes in JUnit Jupiter. This example is tagged for user guide inclusion. ```java include::example$java/example/MyFirstJUnitJupiterRecordTests.java[tags=user_guide] ``` -------------------------------- ### Implement Global Setup/Teardown with LauncherSessionListener Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/advanced-topics/launcher-api.adoc Implement a LauncherSessionListener to manage resources like an HTTP server that should be available for the entire test session. Ensure resources are properly closed after the last test. ```java package example.session; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.LauncherSession; import java.io.Closeable; import java.util.HashMap; import java.util.Map; public class GlobalSetupTeardownListener implements LauncherSessionListener { @Override public void sessionOpened(LauncherSession session) { // Lazy initialization of the HTTP server session.getStore().getOrComputeIfAbsent(CloseableHttpServer.KEY, k -> new CloseableHttpServer()); } @Override public void sessionClosed(LauncherSession session) { // Ensure the server is stopped when the session closes CloseableHttpServer server = (CloseableHttpServer) session.getStore().get(CloseableHttpServer.KEY); if (server != null) { server.close(); } } } ``` ```java package example.session; import com.sun.net.httpserver.HttpServer; import java.io.Closeable; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicInteger; public class CloseableHttpServer implements Closeable { public static final String KEY = CloseableHttpServer.class.getName(); private static final AtomicInteger counter = new AtomicInteger(); private final HttpServer server; public CloseableHttpServer() { try { server = HttpServer.create(new InetSocketAddress(0), 0); server.start(); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void close() { server.stop(0); } public String getHost() { return server.getAddress().getHostName(); } public int getPort() { return server.getAddress().getPort(); } } ``` -------------------------------- ### Kotlin Coroutines with runTest Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/test-classes-and-methods.adoc Demonstrates wrapping regular @Test methods in 'runTest' from kotlinx-coroutines-test for better control over virtual time and skipping delays when testing coroutines. This example is tagged for user guide inclusion. ```kotlin include::example$kotlin/example/KotlinCoroutinesRunTestDemo.kt[tags=user_guide] ``` -------------------------------- ### Run Console Launcher with Classpath Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/running-tests/console-launcher.adoc Run the Console Launcher by specifying the classpath, including classes and test libraries. Replace {OPTIONS} with desired command-line options. ```console $ java -cp classes:testlib/* org.junit.platform.console.ConsoleLauncher ``` -------------------------------- ### Kotlin Coroutines Test Class Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/test-classes-and-methods.adoc Shows how to write test methods and lifecycle methods in Kotlin, including the use of the 'suspend' keyword for testing coroutine-based code. This example is tagged for user guide inclusion. ```kotlin include::example$kotlin/example/KotlinCoroutinesDemo.kt[tags=user_guide] ``` -------------------------------- ### Example of Parallel Test Execution Output Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/migrating-from-junit4.adoc This is an example of the console output when tests are executed in parallel. Threads are dynamically assigned to execute test classes and methods concurrently. ```plaintext ForkJoinPool-1-worker-6 - FooTest::test2 ForkJoinPool-1-worker-7 - BarTest::test3 ForkJoinPool-1-worker-3 - FooTest::test1 ForkJoinPool-1-worker-8 - FooTest::test3 ForkJoinPool-1-worker-5 - BarTest::test2 ForkJoinPool-1-worker-4 - BarTest::test1 ``` -------------------------------- ### Apply Code Formatting with Spotless Source: https://github.com/junit-team/junit-framework/blob/main/CONTRIBUTING.md Use the Spotless Gradle plugin to format new code and add missing license headers to source files. ```gradle gradle spotlessApply ``` -------------------------------- ### Discover tests using Launcher API Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/advanced-topics/launcher-api.adoc This example demonstrates how to discover tests using the JUnit Platform Launcher API. It creates a `LauncherDiscoveryRequest` and uses a `Launcher` to discover tests, resulting in a `TestPlan`. ```java Launcher launcher = LauncherFactory.create(); LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() .selectors(selectPackage("example")) .filters(includeClassNamePattern(".*Demo.*")) .build(); TestPlan testPlan = launcher.discover(request); ``` -------------------------------- ### Kotlin Random Extension Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/extensions/registering-extensions.adoc Example of a Kotlin extension for random number generation. This implementation is basic and may not cover all use cases, for instance, it only supports integers and uses java.util.Random. ```kotlin package example.kotlin.extensions import org.junit.jupiter.api.extension.Extension import org.junit.jupiter.api.extension.ParameterContext import org.junit.jupiter.api.extension.ParameterResolutionException import org.junit.jupiter.api.extension.ParameterResolver import java.util.Random class RandomExtension : Extension, ParameterResolver { override fun supportsParameter(parameterContext: ParameterContext): Boolean = parameterContext.parameter.type.equals(Int::class.java) override fun resolveParameter(parameterContext: ParameterContext): Any = Random().nextInt() } ``` -------------------------------- ### Run Console Launcher with Execute Command Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/running-tests/console-launcher.adoc Execute tests using the Console Launcher JAR. Replace {version} with the actual version number. This example shows a sample output of test execution. ```console $ java -jar junit-platform-console-standalone-{version}.jar execute ├─ JUnit Vintage │ └─ example.JUnit4Tests │ └─ standardJUnit4Test ✔ └─ JUnit Jupiter ├─ StandardTests │ ├─ succeedingTest() ✔ │ └─ skippedTest() ↷ for demonstration purposes └─ A special test case ├─ Custom test name containing spaces ✔ ├─ ╯°□°)╯ ✔ └─ 😱 ✔ Test run finished after 64 ms [ 5 containers found ] [ 0 containers skipped ] [ 5 containers started ] [ 0 containers aborted ] [ 5 containers successful ] [ 0 containers failed ] [ 6 tests found ] [ 1 tests skipped ] [ 5 tests started ] [ 0 tests aborted ] [ 5 tests successful ] [ 0 tests failed ] ``` -------------------------------- ### Java Random Extension Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/extensions/registering-extensions.adoc Example of a Java extension for random number generation. This implementation is basic and may not cover all use cases, for instance, it only supports integers and uses java.util.Random. ```java package example.extensions; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import java.util.Random; class RandomExtension implements Extension, ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext) throws ParameterResolutionException { return parameterContext.getParameter().getType().equals(int.class); } @Override public Object resolveParameter(ParameterContext parameterContext) throws ParameterResolutionException { return new Random().nextInt(); } } ``` -------------------------------- ### Execute tests using Launcher API Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/advanced-topics/launcher-api.adoc This example shows how to execute tests using the JUnit Platform Launcher API. It registers a `SummaryGeneratingListener` to capture test execution results and then executes the tests based on a `LauncherDiscoveryRequest`. ```java Launcher launcher = LauncherFactory.create(); SummaryGeneratingListener listener = new SummaryGeneratingListener(); launcher.registerTestExecutionListener(listener); LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() .selectors(selectClass("example.UsingTheLauncherDemo")) .build(); launcher.execute(request); TestExecutionSummary summary = listener.getSummary(); ``` -------------------------------- ### HttpServerResource Implementation Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/extensions/keeping-state-in-extensions.adoc An example of an HttpServer resource implementing AutoCloseable for automatic cleanup. ```java include::example$java/example/extensions/HttpServerResource.java[tags=user_guide] ``` ```kotlin include::example$kotlin/example/kotlin/extensions/HttpServerResource.kt[tags=user_guide] ``` -------------------------------- ### Kotlin @DisplayName Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates the use of @DisplayName annotation in Kotlin for custom test names. ```kotlin package example.kotlin.example import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test @DisplayName("com.example.DisplayNameDemo") class DisplayNameDemo { @Test @DisplayName("custom display name with spaces") fun `custom display name`() { } @Test @DisplayName("custom display name with emoji 😀") fun `custom display name with emoji`() { } @Test @DisplayName("custom display name with \"quotes\"") fun `custom display name with quotes`() { } @Test @DisplayName("custom display name with special characters like €") fun `custom display name with special characters`() { } } ``` -------------------------------- ### Build LauncherExecutionRequest from TestPlan Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/advanced-topics/launcher-api.adoc Creates a LauncherExecutionRequest directly from a discovered TestPlan. This is an alternative to building from a discovery request, useful when a TestPlan is already available. ```java import org.junit.jupiter.api.Test; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherFactory; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.core.LauncherFactory; import org.junit.platform.launcher.listeners.TestExecutionSummary; class UsingTheLauncherDemo { @Test void cancellationTestPlan() { // tag::cancellation-test-plan[] var discoveryRequest = org.junit.platform.launcher.LauncherDiscoveryRequestBuilder.request() .selectors(org.junit.platform.engine.discovery.DiscoverySelectors.selectClass(UsingTheLauncherDemo.class)) .build(); var launcher = LauncherFactory.create(); var testPlan = launcher.discover(discoveryRequest); var cancellationToken = new org.junit.platform.launcher.CancellationToken(); var listener = new TestExecutionListener() { @Override public void executionFinished(org.junit.platform.engine.TestExecutionResult result) { if (result.getStatus() == org.junit.platform.engine.TestExecutionResult.Status.FAILED) { cancellationToken.cancel(); } } }; var request = org.junit.platform.launcher.LauncherExecutionRequestBuilder.requestWith(testPlan) .build(); launcher.register(listener); TestExecutionSummary summary = launcher.execute(request, cancellationToken); // end::cancellation-test-plan[] } } ``` -------------------------------- ### Java @DisplayName Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates the use of @DisplayName annotation in Java for custom test names. ```java package example.java; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("com.example.DisplayNameDemo") class DisplayNameDemo { @Test @DisplayName("custom display name with spaces") void customDisplayName() { } @Test @DisplayName("custom display name with emoji \uD83D\uDE00") void customDisplayNameWithEmoji() { } @Test @DisplayName("custom display name with \"quotes\"") void customDisplayNameWithQuotes() { } @Test @DisplayName("custom display name with special characters like \\u20AC") void customDisplayNameWithSpecialCharacters() { } } ``` -------------------------------- ### ToStringArgumentConverter Implementation Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc An example implementation of a custom `ArgumentConverter`. This converter is used to demonstrate explicit conversion of arguments. ```java static class ToStringArgumentConverter implements ArgumentConverter { @Override public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { if (source instanceof String) { return source; } return null; } @Override public Type getTargetType() { return Object.class; } } ``` -------------------------------- ### Example of Parallel Execution Output with Pool Size Configuration Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/migrating-from-junit4.adoc This output demonstrates test execution when the pool size is explicitly set. Note that the actual number of threads used may be less than the configured pool size, as the pool adjusts based on workload. ```plaintext ForkJoinPool-1-worker-2 - FooTest::test1 ForkJoinPool-1-worker-4 - BarTest::test2 ForkJoinPool-1-worker-3 - BarTest::test1 ForkJoinPool-1-worker-4 - BarTest::test3 ForkJoinPool-1-worker-2 - FooTest::test2 ForkJoinPool-1-worker-3 - FooTest::test3 ``` -------------------------------- ### Build and Test JUnit Modules Source: https://github.com/junit-team/junit-framework/blob/main/README.md Use this command to build and test all modules of the JUnit framework. Requires JDK 25 and the Gradle Wrapper. ```bash ./gradlew build ``` -------------------------------- ### Kotlin IndicativeSentences with Custom Sentence Fragments Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates customizing sentence fragments with @SentenceFragment in Kotlin. ```kotlin package example.kotlin.example import org.junit.jupiter.api.DisplayNameGeneration import org.junit.jupiter.api.DisplayNameGenerator import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource @DisplayNameGeneration(DisplayNameGenerator.IndicativeSentences::class) class DisplayNameGeneratorDemo { @Test @DisplayName("A year is a leap year, if it is divisible by 4 but not by 100") fun `a year is a leap year`() { } @Test @DisplayName("A year is a leap year, if it is one of the following years") fun `if it is one of the following years`() { } @ParameterizedTest @ValueSource(ints = [2016, 2020, 2048]) @DisplayName("A year is a leap year, if it is one of the following years") fun `year`(year: Int) { } } ``` -------------------------------- ### Java IndicativeSentences with Custom Sentence Fragments Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates customizing sentence fragments with @SentenceFragment in Java. ```java package example.java; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.provider.ValueSource; @DisplayNameGeneration(DisplayNameGenerator.IndicativeSentences.class) class DisplayNameGeneratorDemo { @Test @DisplayName("A year is a leap year, if it is divisible by 4 but not by 100") void a_year_is_a_leap_year() { } @Test @DisplayName("A year is a leap year, if it is one of the following years") void if_it_is_one_of_the_following_years() { } @ParameterizedTest @ValueSource(ints = {2016, 2020, 2048}) @DisplayName("A year is a leap year, if it is one of the following years") void year(int year) { } } ``` -------------------------------- ### Dynamic Tests Demo - Java Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/dynamic-tests.adoc Demonstrates various ways to generate dynamic tests in Java, including returning collections, iterables, iterators, arrays, and streams of DynamicTest instances. Also shows how to create dynamic tests from streams and generate a random number of tests. ```java import org.junit.jupiter.api.DynamicContainer; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.stream.Stream; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; class DynamicTestsDemo { @TestFactory Stream dynamicTestsFromStream() { return Stream.of("level 1", "level 2", "level 3") .map(name -> dynamicTest("Test for " + name, () -> System.out.println("Running test for: " + name))); } @TestFactory Collection dynamicTestsFromCollection() { return Arrays.asList( dynamicTest("simple test 1", () -> assertTrue(true)), dynamicTest("simple test 2", () -> assertEquals(1, 1)) ); } @TestFactory Iterable dynamicTestsFromIterable() { return Arrays.asList( dynamicTest("iterable test 1", () -> assertTrue(true)), dynamicTest("iterable test 2", () -> assertEquals(1, 1)) ); } @TestFactory Iterator dynamicTestsFromIterator() { return Arrays.asList( dynamicTest("iterator test 1", () -> assertTrue(true)), dynamicTest("iterator test 2", () -> assertEquals(1, 1)) ).iterator(); } @TestFactory DynamicTest[] dynamicTestsFromAnArray() { return new DynamicTest[] { dynamicTest("array test 1", () -> assertTrue(true)), dynamicTest("array test 2", () -> assertEquals(1, 1)) }; } @TestFactory Stream dynamicTestsFromIntStream() { return DynamicTest.stream(IntStream.of(1, 2, 3), i -> "Test " + i, i -> assertEquals(i, i)); } @TestFactory Iterator generateRandomNumberOfTests() { // Random number of tests for demonstration purposes int numberOfTests = (int) (Math.random() * 10) + 1; return DynamicTest.stream(IntStream.rangeClosed(1, numberOfTests).iterator(), i -> "Random test " + i, i -> System.out.println("Executing random test " + i)); } @TestFactory Stream dynamicTestsFromStreamFactoryMethod() { return Stream.of("A", "B", "C") .flatMap(s -> DynamicTest.stream(IntStream.rangeClosed(1, 2).iterator(), i -> "Test " + s + "-" + i, i -> System.out.println("Executing test " + s + "-" + i))) .limit(3); // Limit the total number of dynamic tests } @TestFactory DynamicTest dynamicNodeSingleTest() { return dynamicTest("Single dynamic test", () -> assertEquals(4, 2 * 2)); } @TestFactory DynamicContainer dynamicNodeSingleContainer() { return dynamicContainer("Container with one test", Arrays.asList( dynamicTest("Test inside container", () -> assertTrue(true)) )); } @TestFactory DynamicContainer dynamicNodeNestedContainer() { return dynamicContainer("Nested container", Arrays.asList( dynamicContainer("Inner container", Arrays.asList( dynamicTest("Test in inner container", () -> assertTrue(true)) )), dynamicTest("Test in outer container", () -> assertTrue(true)) )); } // Example of an invalid return type (will cause a warning) @TestFactory String invalidReturnType() { return "This is not a DynamicNode or stream of DynamicNodes"; } private void assertTrue(boolean condition) { if (!condition) { throw new AssertionError("Assertion failed"); } } private void assertEquals(int expected, int actual) { if (expected != actual) { throw new AssertionError("Expected: " + expected + ", Actual: " + actual); } } } ``` -------------------------------- ### Create Temporary Directory with Jimfs Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/built-in-extensions.adoc Demonstrates using @TempDir with the Jimfs in-memory file system for temporary directory creation. Ensure Jimfs is on the classpath. ```java import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.assertTrue; class TempDirectoryDemo { @Test void userGuideFactoryJimfs(@TempDir(factory = org.junit.jupiter.api.io.TempDirFactory.JimfsFactory.class) Path testDir) { // user_guide_factory_jimfs assertTrue(testDir.toFile().isDirectory()); } } ``` ```kotlin import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir import java.nio.file.Path import kotlin.test.assertTrue class TempDirectoryDemo { @Test fun userGuideFactoryJimfs(@TempDir(factory = org.junit.jupiter.api.io.TempDirFactory.JimfsFactory::class) testDir: Path) { // user_guide_factory_jimfs assertTrue(testDir.toFile().isDirectory()) } } ``` -------------------------------- ### Application Build Output Directory Structure Source: https://github.com/junit-team/junit-framework/wiki/Testing-with-Jigsaw Shows the directory structure of the compiled main application artifacts after using the 'pro main' command. ```plaintext target/ main/ exploded/ application.api/ foo/ bar/ api/ ApplicationVersion.class ApplicationInterface.class module-info.class application.core/ application.gui/ application.main/ ``` -------------------------------- ### Kotlin ReplaceUnderscores Display Name Generator Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates using the ReplaceUnderscores display name generator in Kotlin. ```kotlin package example.kotlin.example import org.junit.jupiter.api.DisplayNameGeneration import org.junit.jupiter.api.Test import org.junit.jupiter.api.DisplayNameGenerator @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores::class) class DisplayNameGeneratorDemo { @Test fun `a year is not supported`() { } @Test fun `if it is zero`() { } @Test fun `a negative value for year is not supported by the leap year computation`() { } @Test fun `for example year -1 is not supported`() { } @Test fun `for example year -4 is not supported`() { } } ``` -------------------------------- ### View Build Parameters Source: https://github.com/junit-team/junit-framework/blob/main/CONTRIBUTING.md Run this Gradle task to display a comprehensive list of all available build parameters that can influence the build process, such as code coverage options or predictive test selection. ```bash ./gradlew :plugins:build-parameters:parameters ``` -------------------------------- ### Java ReplaceUnderscores Display Name Generator Example Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/display-names.adoc Demonstrates using the ReplaceUnderscores display name generator in Java. ```java package example.java; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.DisplayNameGenerator; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class DisplayNameGeneratorDemo { @Test void a_year_is_not_supported() { } @Test void if_it_is_zero() { } @Test void a_negative_value_for_year_is_not_supported_by_the_leap_year_computation() { } @Test void for_example_year_minus_1_is_not_supported() { } @Test void for_example_year_minus_4_is_not_supported() { } } ``` -------------------------------- ### Enable Open Test Reporting via Console Launcher Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/advanced-topics/junit-platform-reporting.adoc Enable Open Test Reporting and set the output directory using configuration parameters directly in the console launcher command. ```console $ java -jar junit-platform-console-standalone-{version}.jar \ --config=junit.platform.reporting.open.xml.enabled=true \ --config=junit.platform.reporting.output.dir=reports ``` -------------------------------- ### Example CSV File Content Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/writing-tests/parameterized-classes-and-tests.adoc Content of a sample CSV file used with `@CsvFileSource`. Each line represents a record, and the first line can be a header. ```csv include::example$resources/two-column.csv[] ``` -------------------------------- ### Extension1 Callback Implementation Source: https://github.com/junit-team/junit-framework/blob/main/documentation/modules/ROOT/pages/extensions/relative-execution-order-of-user-code-and-extensions.adoc Demonstrates a custom extension with @BeforeEach and @AfterEach callbacks. Used to illustrate wrapping behavior. ```java package com.example.callbacks; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestWatcher; import java.util.Optional; import static com.example.callbacks.Logger.log; public class Extension1 implements TestWatcher { @BeforeEach void beforeEach(ExtensionContext context) { log("Extension1.beforeEach()", context); } @AfterEach void afterEach(ExtensionContext context) { log("Extension1.afterEach()", context); } @Override public void testSuccessful(ExtensionContext context) { log("Extension1.testSuccessful()", context); } @Override public void testFailed(ExtensionContext context, Throwable cause) { log("Extension1.testFailed()", context); } @Override public void testDisabled(ExtensionContext context, Optional reason) { log("Extension1.testDisabled()", context); } @Override public void testAborted(ExtensionContext context, Throwable cause) { log("Extension1.testAborted()", context); } } ```