From 323625f5c9291668e8d3e19fbe1b7863e2be73e7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 20 Aug 2025 10:11:43 +0200 Subject: [PATCH 01/33] Back to snapshots for further development --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 170dccb85da1..000b32c34896 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version = 6.0.0-RC1 +version = 6.0.0-SNAPSHOT # We need more metaspace due to apparent memory leak in Asciidoctor/JRuby org.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError From 5929d3a9bdd282d1f33552767253c0272929260f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 20 Aug 2025 10:18:39 +0200 Subject: [PATCH 02/33] Clone repository in order to load external JavaScript file --- .github/workflows/release.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 886cd39dbf10..defcde8b2c55 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -118,6 +118,11 @@ jobs: permissions: issues: write steps: + - name: Check out repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + persist-credentials: false - name: Close GitHub milestone if: ${{ inputs.dryRun == false }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 @@ -258,9 +263,14 @@ jobs: permissions: contents: write steps: + - name: Check out repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + persist-credentials: false - name: Create GitHub release uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const createGithubRelease = require('./.github/scripts/create-github-release.js'); - createGithubRelease({ github, context }); \ No newline at end of file + createGithubRelease({ github, context }); From 2f0c0bb1ee64820475fbffcb856d6ec1a7b1695e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 20 Aug 2025 10:44:33 +0200 Subject: [PATCH 03/33] Create initial 6.0.0 release notes from template --- .../docs/asciidoc/release-notes/index.adoc | 2 + .../release-notes/release-notes-6.0.0.adoc | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index 0423b30a066e..c99a62643765 100644 --- a/documentation/src/docs/asciidoc/release-notes/index.adoc +++ b/documentation/src/docs/asciidoc/release-notes/index.adoc @@ -17,6 +17,8 @@ authors as well as build tool and IDE vendors. include::{includedir}/link-attributes.adoc[] +include::{basedir}/release-notes-6.0.0.adoc[] + include::{basedir}/release-notes-6.0.0-RC1.adoc[] include::{basedir}/release-notes-6.0.0-M2.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc new file mode 100644 index 000000000000..6465385fea02 --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc @@ -0,0 +1,67 @@ +[[release-notes-6.0.0]] +== 6.0.0 + +*Date of Release:* ❓ + +*Scope:* ❓ + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit-framework-repo}+/milestone/103?closed=1+[6.0.0] milestone page in the JUnit +repository on GitHub. + + +[[release-notes-6.0.0-junit-platform]] +=== JUnit Platform + +[[release-notes-6.0.0-junit-platform-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-junit-platform-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-junit-platform-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-6.0.0-junit-jupiter]] +=== JUnit Jupiter + +[[release-notes-6.0.0-junit-jupiter-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-junit-jupiter-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-junit-jupiter-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-6.0.0-junit-vintage]] +=== JUnit Vintage + +[[release-notes-6.0.0-junit-vintage-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-junit-vintage-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-junit-vintage-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ From 0f5b958dafb199ba12a362261e66e7a9ce068a36 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 20 Aug 2025 13:50:21 +0200 Subject: [PATCH 04/33] Link to upgrade notes in wiki Closes #4830. --- .../docs/asciidoc/release-notes/release-notes-6.0.0.adoc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc index 6465385fea02..825ab588bb2d 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc @@ -9,6 +9,13 @@ For a complete list of all _closed_ issues and pull requests for this release, c link:{junit-framework-repo}+/milestone/103?closed=1+[6.0.0] milestone page in the JUnit repository on GitHub. +[TIP] +.Migration Guide +==== +Please refer to the +https://github.com/junit-team/junit-framework/wiki/Upgrading-to-JUnit-6.0[wiki] for +guidance on upgrading from JUnit 5.x.y to 6.0.0. +==== [[release-notes-6.0.0-junit-platform]] === JUnit Platform From 8043171d0c6de026031f66dbe2767fdbd0a277b0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 20 Aug 2025 14:42:20 +0200 Subject: [PATCH 05/33] Replace 5.13.0 release notes with link in preparation for 6.0.0 release --- .../release-notes/release-notes-5.13.0.adoc | 173 +----------------- 1 file changed, 2 insertions(+), 171 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc index 42c5a8614825..2c752e25d961 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc @@ -15,174 +15,5 @@ * GraalVM: removal of `native-image.properties` files from JARs * Bug fixes and other minor improvements -For a complete list of all _closed_ issues and pull requests for this release, consult the -link:{junit-framework-repo}+/milestone/85?closed=1+[5.13.0-M1], -link:{junit-framework-repo}+/milestone/92?closed=1+[5.13.0-M2], -link:{junit-framework-repo}+/milestone/93?closed=1+[5.13.0-M3], -link:{junit-framework-repo}+/milestone/96?closed=1+[5.13.0-RC1], -and link:{junit-framework-repo}+/milestone/94?closed=1+[5.13.0] milestone pages in the -JUnit repository on GitHub. - - -[[release-notes-5.13.0-overall-improvements]] -=== Overall Changes - -[[release-notes-5.13.0-overall-new-features-and-improvements]] -==== Deprecations and Breaking Changes - -* The JUnit feature in GraalVM Native Build Tools (NBT) has been rewritten to no longer - require JUnit classes to be initialized at build time when running on JDK 22 and later. - Therefore, JUnit's JARs no longer ship with `native-image.properties` files that contain - `--initialize-at-build-time` options (introduced in 5.12.0). Please update to the most - recent version of GraalVM Native Build Tools prior to upgrading to this version of - JUnit. Please refer to the - https://github.com/junit-team/junit-framework/wiki/Upgrading-to-JUnit-5.13[Upgrade Instructions] - in the wiki for details if you're on NBT 0.10.x or earlier. - - -[[release-notes-5.13.0-junit-platform]] -=== JUnit Platform - -[[release-notes-5.13.0-junit-platform-bug-fixes]] -==== Bug Fixes - -* Notify `LauncherDiscoveryListener` implementation registered via `LaucherConfig` or on - the `Launcher` of `selectorProcessed` events. -* Reintroduce support for JVM shutdown hooks when using the `-cp`/`--classpath` option of - the `ConsoleLauncher`. Prior to this release, the created class loader was closed prior - to JVM shutdown hooks being invoked, which caused hooks to fail with a - `ClassNotFoundException` when loading classes during shutdown. -* Fix support of `--uid` and `--select-unique-id` options in the console launcher. - -[[release-notes-5.13.0-junit-platform-new-features-and-improvements]] -==== New Features and Improvements - -* Introduce a mechanism for `TestEngine` implementations to report issues encountered - during test discovery. If an engine reports a `DiscoveryIssue` with a `Severity` equal - to or higher than a configurable critical severity, its tests will not be executed. - Instead, the engine will be reported as failed during execution with a failure message - listing all critical issues. Non-critical issues will be logged but will not prevent the - engine from executing its tests. The critical severity can be configured via a new - configuration parameter and, currently, defaults to `ERROR`. Please refer to the - <<../user-guide/index.adoc#running-tests-discovery-issues, User Guide>> for details. -+ -If you're a test engine maintainer, please see the -<<../user-guide/index.adoc#test-engines-discovery-issues, User Guide>> for details on how -to start reporting discovery issues. -* Start reporting discovery issues for problematic `@Suite` classes: - - Invalid `@Suite` class declarations (for example, when `private`) - - Invalid `@BeforeSuite`/`@AfterSuite` method declarations (for example, when not - `static`) - - Cyclic dependencies between `@Suite` classes -* Introduce resource management mechanism that allows preparing and sharing state across - executions or test engines via stores that are scoped to a `LauncherSession` or - `ExecutionRequest`. The Jupiter API uses these stores as ancestors to the `Store` - instances accessible via `ExtensionContext` and provides a new method to access them - directly. Please refer to the User Guide for examples of managing - <<../user-guide/index.adoc#launcher-api-launcher-session-listeners-tool-example-usage, session-scoped>> - and - <<../user-guide/index.adoc#launcher-api-managing-state-across-test-engines, request-scoped>> - resources. -* New `ConsoleLauncher` options `--redirect-stdout` and `--redirect-stderr` for - redirecting `stdout` and `stderr` output streams to files. -* Add `TestDescriptor.Visitor.composite(List)` factory method for creating a composite - visitor that delegates to the given visitors in order. -* Introduce test _discovery_ support in `EngineTestKit` to ease testing for discovery - issues produced by a `TestEngine`. Please refer to the - <<../user-guide/index.adoc#testkit-engine, User Guide>> for details. -* Make validation of including `EngineFilters` more strict to avoid misconfiguration, for - example, due to typos. Prior to this release, an exception was only thrown when _none_ - of a filter's included IDs matched any engine. Now, an exception is thrown if at least - one included ID across all filters did not match any engine. - - -[[release-notes-5.13.0-junit-jupiter]] -=== JUnit Jupiter - -[[release-notes-5.13.0-junit-jupiter-bug-fixes]] -==== Bug Fixes - -* If the `autoCloseArguments` attribute in `@ParameterizedTest` is set to `true`, all - arguments returned by registered `ArgumentsProvider` implementations are now closed even - if the test method declares fewer parameters. -* `AutoCloseable` arguments returned by an `ArgumentsProvider` are now closed even if they - are wrapped with `Named`. -* `AutoCloseable` arguments returned by an `ArgumentsProvider` are now closed even if a - failure happens prior to invoking the parameterized method. -* Validate _all_ versions specified in `@EnabledOnJre` and `@DisabledOnJre` annotations. - -[[release-notes-5.13.0-junit-jupiter-new-features-and-improvements]] -==== New Features and Improvements - -* New `@ClassTemplate` annotation and `ClassTemplateInvocationContextProvider` API that - allow declaring a top-level or `@Nested` test class as a template to be invoked multiple - times. This may be used, for example, to inject different parameters to be used by all - tests in the class template or to set up each invocation of the class template - differently. Please refer to the - <<../user-guide/index.adoc#writing-tests-class-templates, User Guide>> for details. -* New `BeforeClassTemplateInvocationCallback` and `AfterClassTemplateInvocationCallback` - extension callback interfaces allow implementing extensions that are invoked before and - after each invocation of a class template. -* New `@ParameterizedClass` support that builds on `@ClassTemplate` and allows declaring a - top-level or `@Nested` test class as a parameterized test class to be invoked multiple - times with different arguments. The same `@...Source` annotations supported with - `@ParameterizedTest` may be used to provide arguments via constructor or field - injection. Please refer to the - <<../user-guide/index.adoc#writing-tests-parameterized-tests, User Guide>> for details. -* New `@ParameterizedClass`-specific - `@BeforeParameterizedClassInvocation`/`@AfterParameterizedClassInvocation` lifecycle - methods that are invoked once before/after each invocation of the parameterized class. -* Provide access to the parameters and resolved arguments of a `@ParameterizedTest` or - `@ParameterizedClass` by storing `ParameterInfo` in the `ExtensionContext.Store` for - retrieval by other extensions. Please refer to the - link:../api/org.junit.jupiter.params/org/junit/jupiter/params/support/ParameterInfo.html[Javadoc] - for details. -* New `@SentenceFragment` annotation which allows one to supply custom text for individual - sentence fragments when using the `IndicativeSentences` `DisplayNameGenerator`. See the - updated documentation in the - <<../user-guide/index.adoc#writing-tests-display-name-generator, User Guide>> for an - example. -* New `TestTemplateInvocationContext.prepareInvocation(ExtensionContext)` callback method - which allows extensions to prepare the `ExtensionContext` before the test template - method is invoked. This may be used, for example, to store entries in the - `ExtensionContext.Store` to benefit from its cleanup support or for retrieval by other - extensions. -* Start reporting discovery issues for potentially problematic test classes: - - Invalid `@Test` and `@TestTemplate` method declarations (for example, when return - type is not `void`) - - Invalid `@TestFactory` methods (for example, when return type is invalid) - - Multiple method-level annotations (for example, `@Test` and `@TestTemplate`) - - Invalid test class and `@Nested` class declarations (for example, `static` `@Nested` - classes) - - Potentially missing `@Nested` annotations (for example, non-abstract inner classes - that contain test methods) - - Invalid lifecycle method declarations (for example, when `private`) - - Invalid `@Tag` syntax - - Blank `@DisplayName` declarations - - Blank `@SentenceFragment` declarations - - `@BeforeParameterizedClassInvocation` and `@AfterParameterizedClassInvocation` - methods declared in non-parameterized test classes -* By default, `AutoCloseable` objects put into `ExtensionContext.Store` are now treated - like instances of `CloseableResource` (which has been deprecated) and are closed - automatically when the store is closed at the end of the test lifecycle. It's possible - to <<../user-guide/index.adoc#extensions-keeping-state-autocloseable-support, revert to the old behavior>> - via a configuration parameter. Please also see the - <<../user-guide/index.adoc#extensions-keeping-state-autocloseable-migration, migration note>> - for third-party extensions wanting to support both JUnit 5.13 and earlier versions. -* `java.util.Locale` arguments are now converted according to the IETF BCP 47 language tag - format. See the - <<../user-guide/index.adoc#writing-tests-parameterized-tests-argument-conversion-implicit, User Guide>> - for details. -* Avoid reporting potentially misleading validation exception for `@ParameterizedClass` - test classes and `@ParameterizedTest` methods as suppressed exception for earlier - failures. -* Add support for Kotlin `Sequence` to `@MethodSource`, `@FieldSource`, and - `@TestFactory`. -* Allow publishing files to an existing directory via `TestReporter` and - `ExtensionContext`, for example, when re-running a test class. - - -[[release-notes-5.13.0-junit-vintage]] -=== JUnit Vintage - -No changes. +For complete details consult the +https://junit.org/junit5/docs/5.13.0/release-notes/index.html[5.13.0 Release Notes] online. From c672142a45c8d3963a045cfca0f8294ae14af507 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 20 Aug 2025 11:52:59 +0200 Subject: [PATCH 06/33] Make artifacts built by JitPack consumable in Gradle or Maven projects * Use JitPack's version but replace commit sha and counter with SNAPSHOT * Use JitPack's group and artifact ID * Disable artifact signing --- .jitpack.yml | 9 ++++++++- gradle/plugins/build-parameters/build.gradle.kts | 8 ++++++++ ...unitbuild.java-library-conventions.gradle.kts | 8 +++++--- .../junitbuild.publishing-conventions.gradle.kts | 16 ++++++++++------ junit-bom/junit-bom.gradle.kts | 7 ++++++- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/.jitpack.yml b/.jitpack.yml index 4b239cdf1e36..fd83c0c2efde 100644 --- a/.jitpack.yml +++ b/.jitpack.yml @@ -3,4 +3,11 @@ before_install: - sdk install java 24-open - sdk use java 24-open install: - - ./gradlew --show-version javaToolchains publishToMavenLocal + - | + ./gradlew \ + --show-version \ + -Pjitpack.version=$VERSION \ + -Ppublishing.group=$GROUP.$ARTIFACT \ + -Ppublishing.signArtifacts=false \ + javaToolchains \ + publishToMavenLocal diff --git a/gradle/plugins/build-parameters/build.gradle.kts b/gradle/plugins/build-parameters/build.gradle.kts index f2db3d75afaa..8cdab340d4c3 100644 --- a/gradle/plugins/build-parameters/build.gradle.kts +++ b/gradle/plugins/build-parameters/build.gradle.kts @@ -93,6 +93,14 @@ buildParameters { bool("signArtifacts") { description = "Sign artifacts before publishing them to Maven repos" } + string("group") { + description = "Group ID for published Maven artifacts" + } + } + group("jitpack") { + string("version") { + description = "The version computed by Jitpack" + } } group("manifest") { string("buildTimestamp") { diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts index 6b5be1377708..3f1e846f0e5f 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts @@ -113,9 +113,11 @@ if (project in mavenizedProjects) { publications { named("maven") { from(components["java"]) - versionMapping { - allVariants { - fromResolutionResult() + if (!buildParameters.jitpack.version.isPresent) { + versionMapping { + allVariants { + fromResolutionResult() + } } } pom { diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts index 0783f037b2be..5dc22b4e6bfb 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts @@ -11,12 +11,13 @@ val jupiterProjects: List by rootProject val platformProjects: List by rootProject val vintageProjects: List by rootProject -group = when (project) { - in jupiterProjects -> "org.junit.jupiter" - in platformProjects -> "org.junit.platform" - in vintageProjects -> "org.junit.vintage" - else -> "org.junit" -} +group = buildParameters.publishing.group + .getOrElse(when (project) { + in jupiterProjects -> "org.junit.jupiter" + in platformProjects -> "org.junit.platform" + in vintageProjects -> "org.junit.vintage" + else -> "org.junit" + }) val signArtifacts = buildParameters.publishing.signArtifacts.getOrElse(!(project.version.isSnapshot() || buildParameters.ci)) @@ -33,6 +34,9 @@ tasks.withType().configureEach { publishing { publications { create("maven") { + version = buildParameters.jitpack.version + .map { value -> "(.+)-[0-9a-f]+-\\d+".toRegex().matchEntire(value)!!.groupValues[1] + "-SNAPSHOT" } + .getOrElse(project.version.toString()) pom { name.set(provider { project.description ?: "${project.group}:${project.name}" diff --git a/junit-bom/junit-bom.gradle.kts b/junit-bom/junit-bom.gradle.kts index 5e9107a5ac1f..1671c700f9bc 100644 --- a/junit-bom/junit-bom.gradle.kts +++ b/junit-bom/junit-bom.gradle.kts @@ -10,7 +10,12 @@ dependencies { val mavenizedProjects: List by rootProject.extra mavenizedProjects.sorted() .filter { it.name != "junit-platform-console-standalone" } - .forEach { api("${it.group}:${it.name}:${it.version}") } + .forEach { + val version = buildParameters.jitpack.version + .map { value -> "(.+)-[0-9a-f]+-\\d+".toRegex().matchEntire(value)!!.groupValues[1] + "-SNAPSHOT" } + .getOrElse(it.version.toString()) + api("${it.group}:${it.name}:${version}") + } } } From 2a9e7b5e4097c095a23031e05ef81a4f9acbe1d1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:48:09 +0000 Subject: [PATCH 07/33] Update codecov/codecov-action action to v5.5.0 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 18e9f54c0908..1c9cb8c5cdd9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,7 +46,7 @@ jobs: jacocoRootReport \ --no-configuration-cache # Disable configuration cache due to https://github.com/diffplug/spotless/issues/2318 - name: Upload to Codecov.io - uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 + uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # v5.5.0 with: token: ${{ secrets.CODECOV_TOKEN }} From 5422916885e68934349393d237b239e67ec3bf68 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 06:37:40 +0000 Subject: [PATCH 08/33] Update actions/setup-java action to v5 --- .github/actions/run-gradle/action.yml | 2 +- .github/actions/setup-test-jdk/action.yml | 4 ++-- .github/workflows/cross-version.yml | 4 ++-- .github/workflows/gradle-dependency-submission.yml | 2 +- .github/workflows/release.yml | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/run-gradle/action.yml b/.github/actions/run-gradle/action.yml index 5e04e02b5067..cddc34961378 100644 --- a/.github/actions/run-gradle/action.yml +++ b/.github/actions/run-gradle/action.yml @@ -11,7 +11,7 @@ inputs: runs: using: "composite" steps: - - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 id: setup-gradle-jdk with: distribution: temurin diff --git a/.github/actions/setup-test-jdk/action.yml b/.github/actions/setup-test-jdk/action.yml index e6ff54ca9ed1..0c372f657e35 100644 --- a/.github/actions/setup-test-jdk/action.yml +++ b/.github/actions/setup-test-jdk/action.yml @@ -8,14 +8,14 @@ inputs: runs: using: "composite" steps: - - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: ${{ inputs.distribution }} java-version: 8 check-latest: true - shell: bash run: echo "JDK8=$JAVA_HOME" >> $GITHUB_ENV # zizmor: ignore[github-env] - - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5 with: distribution: ${{ inputs.distribution }} java-version: 17 diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 0a7f0ea43888..80bcbcbd0e37 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -50,7 +50,7 @@ jobs: version: latest - name: "Set up JDK ${{ matrix.jdk.version }} (${{ matrix.jdk.distribution || 'temurin' }})" if: matrix.jdk.type == 'ga' - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: ${{ matrix.jdk.distribution || 'temurin' }} java-version: ${{ matrix.jdk.version }} @@ -91,7 +91,7 @@ jobs: with: distribution: semeru - name: 'Set up JDK ${{ matrix.jdk }}' - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: semeru java-version: ${{ matrix.jdk }} diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index cfdc9a9728f8..02a9914ac191 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -23,7 +23,7 @@ jobs: fetch-depth: 1 persist-credentials: false - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 24 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index defcde8b2c55..e92b8f9619cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: ref: develop/6.x persist-credentials: false - name: Set up JDK - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: 24 distribution: temurin @@ -227,7 +227,7 @@ jobs: ref: develop/6.x persist-credentials: true - name: Set up JDK - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: 24 distribution: temurin From 946c522aeb4790ff3c54758f1454b8d6ff183e18 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 21 Aug 2025 09:07:23 +0200 Subject: [PATCH 09/33] Use full version for actions/setup-java --- .github/actions/setup-test-jdk/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-test-jdk/action.yml b/.github/actions/setup-test-jdk/action.yml index 0c372f657e35..f5ad261ed559 100644 --- a/.github/actions/setup-test-jdk/action.yml +++ b/.github/actions/setup-test-jdk/action.yml @@ -15,7 +15,7 @@ runs: check-latest: true - shell: bash run: echo "JDK8=$JAVA_HOME" >> $GITHUB_ENV # zizmor: ignore[github-env] - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5 + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: ${{ inputs.distribution }} java-version: 17 From 6bafa4c119c80ae88e572f2be44030480a9b83cb Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:25:04 +0200 Subject: [PATCH 10/33] Declare methods in consistent order --- .../api/extension/ExtensionContext.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java index cc52c99f266d..8a840b7103c5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java @@ -134,6 +134,22 @@ public interface ExtensionContext { */ Optional> getTestClass(); + /** + * Get the required {@link Class} associated with the current test + * or container. + * + *

Use this method as an alternative to {@link #getTestClass()} for use + * cases in which the test class is required to be present. + * + * @return the test class; never {@code null} + * @throws PreconditionViolationException if the test class is not present + * in this {@code ExtensionContext} + */ + default Class getRequiredTestClass() { + return Preconditions.notNull(getTestClass().orElse(null), + "Illegal state: required test class is not present in the current ExtensionContext"); + } + /** * Get the enclosing test classes of the current test or container. * @@ -159,22 +175,6 @@ public interface ExtensionContext { @API(status = MAINTAINED, since = "5.13.3") List> getEnclosingTestClasses(); - /** - * Get the required {@link Class} associated with the current test - * or container. - * - *

Use this method as an alternative to {@link #getTestClass()} for use - * cases in which the test class is required to be present. - * - * @return the test class; never {@code null} - * @throws PreconditionViolationException if the test class is not present - * in this {@code ExtensionContext} - */ - default Class getRequiredTestClass() { - return Preconditions.notNull(getTestClass().orElse(null), - "Illegal state: required test class is not present in the current ExtensionContext"); - } - /** * Get the {@link Lifecycle} of the {@linkplain #getTestInstance() test * instance} associated with the current test or container, if available. From cfdeeffedf29bf309fddbfcdddedd3b06f69ea1f Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:33:00 +0200 Subject: [PATCH 11/33] =?UTF-8?q?Add=20missing=20@=E2=81=A0deprecated,=20@?= =?UTF-8?q?=E2=81=A0since,=20&=20@=E2=81=A0API=20tags=20in=20ExtensionCont?= =?UTF-8?q?ext.Store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit updates NamespacedHierarchicalStore as well. Closes #4858 --- .../jupiter/api/extension/ExtensionContext.java | 15 ++++++++------- .../store/NamespacedHierarchicalStore.java | 12 ++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java index 8a840b7103c5..335c50f8f952 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java @@ -614,10 +614,9 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see #computeIfAbsent(Object, Function, Class) * @see CloseableResource * @see AutoCloseable - * * @deprecated Please use {@link #computeIfAbsent(Class)} instead. */ - @Deprecated + @Deprecated(since = "6.0") @API(status = DEPRECATED, since = "6.0") default V getOrComputeIfAbsent(Class type) { return computeIfAbsent(type); @@ -691,11 +690,9 @@ default V computeIfAbsent(Class type) { * @see #computeIfAbsent(Object, Function, Class) * @see CloseableResource * @see AutoCloseable - * - * @deprecated Please use {@link #computeIfAbsent(Object, Function)} - * instead. + * @deprecated Please use {@link #computeIfAbsent(Object, Function)} instead. */ - @Deprecated + @Deprecated(since = "6.0") @API(status = DEPRECATED, since = "6.0") @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator); @@ -734,6 +731,7 @@ default V computeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ + @API(status = MAINTAINED, since = "6.0") Object computeIfAbsent(K key, Function defaultCreator); /** @@ -765,8 +763,9 @@ default V computeIfAbsent(Class type) { * @see #computeIfAbsent(Object, Function, Class) * @see CloseableResource * @see AutoCloseable + * @deprecated Please use {@link #computeIfAbsent(Object, Function, Class)} instead. */ - @Deprecated + @Deprecated(since = "6.0") @API(status = DEPRECATED, since = "6.0") @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); @@ -797,11 +796,13 @@ default V computeIfAbsent(Class type) { * @param the key type * @param the value type * @return the value; never {@code null} + * @since 6.0 * @see #computeIfAbsent(Class) * @see #computeIfAbsent(Object, Function) * @see CloseableResource * @see AutoCloseable */ + @API(status = MAINTAINED, since = "6.0") V computeIfAbsent(K key, Function defaultCreator, Class requiredType); /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java index 5e9c3157ffee..30d84de0f491 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java @@ -189,11 +189,9 @@ public void close() { * @return the stored value; may be {@code null} * @throws NamespacedHierarchicalStoreException if this store has already been * closed - * - * @deprecated Please use - * {@link #computeIfAbsent(Object, Object, Function)} instead. + * @deprecated Please use {@link #computeIfAbsent(Object, Object, Function)} instead. */ - @Deprecated + @Deprecated(since = "6.0") @API(status = DEPRECATED, since = "6.0") public @Nullable Object getOrComputeIfAbsent(N namespace, K key, Function defaultCreator) { @@ -262,11 +260,9 @@ public Object computeIfAbsent(N namespace, K key, Function @Nullable V getOrComputeIfAbsent(N namespace, K key, Function defaultCreator, Class requiredType) From 3c50f3743245ded87014fec2dcc104ae21935d0f Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 21 Aug 2025 14:05:18 +0200 Subject: [PATCH 12/33] =?UTF-8?q?Add=20missing=20since=20attributes=20to?= =?UTF-8?q?=20@=E2=81=A0Deprecated=20declarations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #4859 --- .../junit/jupiter/api/DisplayNameGenerator.java | 4 ++-- .../jupiter/api/extension/ExtensionContext.java | 2 +- .../extension/TestInstantiationAwareExtension.java | 4 ++-- .../junit/jupiter/params/ParameterizedTest.java | 14 +++++++------- .../provider/AnnotationBasedArgumentsProvider.java | 2 +- .../jupiter/params/provider/ArgumentsProvider.java | 2 +- .../commons/support/AnnotationSupport.java | 2 +- .../platform/commons/support/SearchOption.java | 4 ++-- .../junit/platform/engine/ExecutionRequest.java | 9 +++++++-- .../java/org/junit/platform/engine/Filter.java | 1 + .../java/org/junit/platform/launcher/Launcher.java | 4 ++-- .../java/org/junit/platform/launcher/TestPlan.java | 4 ++-- .../SuiteLauncherDiscoveryRequestBuilder.java | 2 +- 13 files changed, 30 insertions(+), 24 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java index c7dbd2e5f155..83612b5927c4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java @@ -107,7 +107,7 @@ public interface DisplayNameGenerator { * @deprecated in favor of {@link #generateDisplayNameForNestedClass(List, Class)} */ @API(status = DEPRECATED, since = "5.12") - @Deprecated + @Deprecated(since = "5.12") default String generateDisplayNameForNestedClass(Class nestedClass) { throw new UnsupportedOperationException( "Implement generateDisplayNameForNestedClass(List>, Class) instead"); @@ -153,7 +153,7 @@ default String generateDisplayNameForNestedClass(List> enclosingInstanc * @deprecated in favor of {@link #generateDisplayNameForMethod(List, Class, Method)} */ @API(status = DEPRECATED, since = "5.12") - @Deprecated + @Deprecated(since = "5.12") default String generateDisplayNameForMethod(Class testClass, Method testMethod) { throw new UnsupportedOperationException( "Implement generateDisplayNameForMethod(List>, Class, Method) instead"); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java index 335c50f8f952..fa44203dba1f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java @@ -506,7 +506,7 @@ interface Store { * @since 5.1 * @deprecated Please extend {@code AutoCloseable} directly. */ - @Deprecated + @Deprecated(since = "5.13") @API(status = DEPRECATED, since = "5.13") interface CloseableResource { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java index 2045d264080f..b55725a7a7ae 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java @@ -118,8 +118,8 @@ enum ExtensionContextScope { * * @see #DEFAULT_SCOPE_PROPERTY_NAME */ - @API(status = DEPRECATED, since = "5.12") // - @Deprecated + @Deprecated(since = "5.12") // + @API(status = DEPRECATED, since = "5.12") DEFAULT, /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java index 68b8f3d41918..f5af060b5bcf 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java @@ -148,7 +148,7 @@ * instead. */ @API(status = DEPRECATED, since = "5.13") - @Deprecated + @Deprecated(since = "5.13") String DISPLAY_NAME_PLACEHOLDER = ParameterizedInvocationConstants.DISPLAY_NAME_PLACEHOLDER; /** @@ -161,7 +161,7 @@ * {@link ParameterizedInvocationConstants#INDEX_PLACEHOLDER} instead. */ @API(status = DEPRECATED, since = "5.13") - @Deprecated + @Deprecated(since = "5.13") String INDEX_PLACEHOLDER = ParameterizedInvocationConstants.INDEX_PLACEHOLDER; /** @@ -173,7 +173,7 @@ * {@link ParameterizedInvocationConstants#ARGUMENTS_PLACEHOLDER} instead. */ @API(status = DEPRECATED, since = "5.13") - @Deprecated + @Deprecated(since = "5.13") String ARGUMENTS_PLACEHOLDER = ParameterizedInvocationConstants.ARGUMENTS_PLACEHOLDER; /** @@ -188,7 +188,7 @@ * instead. */ @API(status = DEPRECATED, since = "5.13") - @Deprecated + @Deprecated(since = "5.13") String ARGUMENTS_WITH_NAMES_PLACEHOLDER = ParameterizedInvocationConstants.ARGUMENTS_WITH_NAMES_PLACEHOLDER; /** @@ -204,7 +204,7 @@ * instead. */ @API(status = DEPRECATED, since = "5.13") - @Deprecated + @Deprecated(since = "5.13") String ARGUMENT_SET_NAME_PLACEHOLDER = ParameterizedInvocationConstants.ARGUMENT_SET_NAME_PLACEHOLDER; /** @@ -222,7 +222,7 @@ * instead. */ @API(status = DEPRECATED, since = "5.13") - @Deprecated + @Deprecated(since = "5.13") String ARGUMENT_SET_NAME_OR_ARGUMENTS_WITH_NAMES_PLACEHOLDER = // ParameterizedInvocationConstants.ARGUMENT_SET_NAME_OR_ARGUMENTS_WITH_NAMES_PLACEHOLDER; @@ -239,7 +239,7 @@ * {@link ParameterizedInvocationConstants#DEFAULT_DISPLAY_NAME} instead. */ @API(status = DEPRECATED, since = "5.13") - @Deprecated + @Deprecated(since = "5.13") String DEFAULT_DISPLAY_NAME = ParameterizedInvocationConstants.DEFAULT_DISPLAY_NAME; /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java index 608a079c5db6..e14b781b0d1b 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java @@ -69,7 +69,7 @@ public Stream provideArguments(ParameterDeclarations parame * {@link #provideArguments(ParameterDeclarations, ExtensionContext, Annotation)} * instead. */ - @Deprecated + @Deprecated(since = "5.13") @API(status = DEPRECATED, since = "5.13") protected Stream provideArguments(ExtensionContext context, A annotation) { throw new JUnitException(""" diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java index ec362ffc7f46..d38595379442 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java @@ -54,7 +54,7 @@ public interface ArgumentsProvider { * @deprecated Please implement * {@link #provideArguments(ParameterDeclarations, ExtensionContext)} instead. */ - @Deprecated + @Deprecated(since = "5.13") @API(status = DEPRECATED, since = "5.13") default Stream provideArguments(@SuppressWarnings("unused") ExtensionContext context) throws Exception { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java index 32bd731b217e..a3ba2a1abe70 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java @@ -176,7 +176,7 @@ public static Optional findAnnotation(@Nullable Annota * {@link #findAnnotation(Class, Class, List)} (for * {@code SearchOption.INCLUDE_ENCLOSING_CLASSES}) instead */ - @Deprecated + @Deprecated(since = "1.12") @API(status = DEPRECATED, since = "1.12") @SuppressWarnings("deprecation") public static Optional findAnnotation(@Nullable Class clazz, Class annotationType, diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/SearchOption.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/SearchOption.java index ab3d804c5b13..87d0df4900d3 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/SearchOption.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/SearchOption.java @@ -22,7 +22,7 @@ * @see #INCLUDE_ENCLOSING_CLASSES * @deprecated because there is only a single non-deprecated search option left */ -@Deprecated +@Deprecated(since = "1.12") @API(status = DEPRECATED, since = "1.12") public enum SearchOption { @@ -43,7 +43,7 @@ public enum SearchOption { * @deprecated because it is preferable to inspect the runtime enclosing * types of a class rather than where they are declared. */ - @Deprecated // + @Deprecated(since = "1.12") // @API(status = DEPRECATED, since = "1.12") INCLUDE_ENCLOSING_CLASSES diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java index 16afe7fae878..feb1d30f2999 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java @@ -47,7 +47,12 @@ public class ExecutionRequest { private final @Nullable NamespacedHierarchicalStore requestLevelStore; private final CancellationToken cancellationToken; - @Deprecated + /** + * @deprecated Use + * {@link #create(TestDescriptor, EngineExecutionListener, ConfigurationParameters, OutputDirectoryProvider, NamespacedHierarchicalStore, CancellationToken)} + * instead. + */ + @Deprecated(since = "1.11") @API(status = DEPRECATED, since = "1.11") public ExecutionRequest(TestDescriptor rootTestDescriptor, EngineExecutionListener engineExecutionListener, ConfigurationParameters configurationParameters) { @@ -81,7 +86,7 @@ private ExecutionRequest(TestDescriptor rootTestDescriptor, EngineExecutionListe * @since 1.9 * @deprecated without replacement */ - @Deprecated + @Deprecated(since = "1.11") @API(status = DEPRECATED, since = "1.11") public static ExecutionRequest create(TestDescriptor rootTestDescriptor, EngineExecutionListener engineExecutionListener, ConfigurationParameters configurationParameters) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java index 83511c09bdf8..e7ab3f3474af 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java @@ -94,6 +94,7 @@ static Filter composeFilters(Collection> filters) { * * @param adaptee the filter to be adapted * @param converter the converter function to apply + * @deprecated without replacement */ @API(status = DEPRECATED, since = "6.0") @Deprecated(since = "6.0", forRemoval = true) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java index 2e87fa874152..50847f5e15c7 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java @@ -110,7 +110,7 @@ public interface Launcher { * @param listeners additional test execution listeners; never {@code null} * @deprecated Please use {@link #execute(LauncherExecutionRequest)} instead. */ - @Deprecated + @Deprecated(since = "6.0") @API(status = DEPRECATED, since = "6.0") default void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { var executionRequest = LauncherExecutionRequestBuilder.request(launcherDiscoveryRequest) // @@ -136,7 +136,7 @@ default void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExec * @since 1.4 * @deprecated Please use {@link #execute(LauncherExecutionRequest)} instead. */ - @Deprecated + @Deprecated(since = "6.0") @API(status = DEPRECATED, since = "6.0") default void execute(TestPlan testPlan, TestExecutionListener... listeners) { var executionRequest = LauncherExecutionRequestBuilder.request(testPlan) // diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java index 9ece4d94c9df..2ce022e05c53 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java @@ -180,10 +180,10 @@ public Set getChildren(UniqueId parentId) { * @return the identifier with the supplied unique ID; never {@code null} * @throws PreconditionViolationException if no {@code TestIdentifier} * with the supplied unique ID is present in this test plan - * @deprecated Use {@link #getTestIdentifier(UniqueId)} + * @deprecated Use {@link #getTestIdentifier(UniqueId)} instead. */ @API(status = DEPRECATED, since = "1.10", consumers = "Gradle") - @Deprecated + @Deprecated(since = "1.10") public TestIdentifier getTestIdentifier(String uniqueId) throws PreconditionViolationException { Preconditions.notBlank(uniqueId, "unique ID must not be null or blank"); return getTestIdentifier(UniqueId.parse(uniqueId)); diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java index 72e486adb196..70b18f4b90f3 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java @@ -216,7 +216,7 @@ void listener(LauncherDiscoveryListener listener) { * {@link #applyConfigurationParametersFromSuite} and * {@link #applySelectorsAndFiltersFromSuite} */ - @Deprecated + @Deprecated(since = "1.11") SuiteLauncherDiscoveryRequestBuilder suite(Class suiteClass) { Preconditions.notNull(suiteClass, "Suite class must not be null"); applyConfigurationParametersFromSuite(suiteClass); From b4e04f9c93afd4df9ca98b1351ab8525fe252de2 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 21 Aug 2025 14:07:34 +0200 Subject: [PATCH 13/33] Delete obsolete SuiteLauncherDiscoveryRequestBuilder.suite() method See #4690 --- .../SuiteLauncherDiscoveryRequestBuilder.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java index 70b18f4b90f3..0f0a4b031ef5 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java @@ -205,25 +205,6 @@ void listener(LauncherDiscoveryListener listener) { delegate.listeners(listener); } - /** - * Apply a suite's annotation-based configuration, selectors, and filters to - * this builder. - * - * @param suiteClass the class to apply the annotations from; never {@code null} - * @return this builder for method chaining - * @see org.junit.platform.suite.api.Suite - * @deprecated as of JUnit Platform 1.11 in favor of - * {@link #applyConfigurationParametersFromSuite} and - * {@link #applySelectorsAndFiltersFromSuite} - */ - @Deprecated(since = "1.11") - SuiteLauncherDiscoveryRequestBuilder suite(Class suiteClass) { - Preconditions.notNull(suiteClass, "Suite class must not be null"); - applyConfigurationParametersFromSuite(suiteClass); - applySelectorsAndFiltersFromSuite(suiteClass); - return this; - } - /** * Apply a suite's annotation-based configuration to this builder. * From 81d71d62455940cb2adf6706dab783e79e98c2d7 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:53:36 +0200 Subject: [PATCH 14/33] Restructure DiscoverySelectorsTests regarding DiscoverySelectorIdentifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit basically just moves the associated tests to the correct @⁠Nested test classes, renames test methods for consistency, etc. --- .../discovery/DiscoverySelectorsTests.java | 140 +++++++++--------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java index 0b8dd823168a..36808926fe37 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java @@ -94,11 +94,6 @@ void selectUriByURI() { assertEquals(uri, selector.getUri()); } - } - - @Nested - class SelectFileTests { - @Test void parseUriSelector() { var selector = parseIdentifier(selectUri("https://junit.org")); @@ -108,6 +103,11 @@ void parseUriSelector() { .isEqualTo(URI.create("https://junit.org")); } + } + + @Nested + class SelectFileTests { + @SuppressWarnings("DataFlowIssue") @Test void selectFileByName() { @@ -174,11 +174,6 @@ void selectFileByFileReferenceAndPosition() throws Exception { assertEquals(FilePosition.from(12, 34), selector.getPosition().orElseThrow()); } - } - - @Nested - class SelectDirectoryTests { - @Test void parseFileSelectorWithRelativePath() { var path = "src/test/resources/do_not_delete_me.txt"; @@ -232,6 +227,11 @@ void parseFileSelectorWithAbsolutePathAndFilePosition() { Optional.of(filePosition)); } + } + + @Nested + class SelectDirectoryTests { + @SuppressWarnings("DataFlowIssue") @Test void selectDirectoryByName() { @@ -263,11 +263,6 @@ void selectDirectoryByFileReference() throws Exception { assertEquals(Path.of(path), selector.getPath()); } - } - - @Nested - class SelectClasspathResourceTests { - @Test void parseDirectorySelectorWithRelativePath() { var path = "src/test/resources"; @@ -294,6 +289,11 @@ void parseDirectorySelectorWithAbsolutePath() { .containsExactly(path, new File(path), Path.of(path)); } + } + + @Nested + class SelectClasspathResourceTests { + @SuppressWarnings("DataFlowIssue") @Test void selectClasspathResourcesPreconditions() { @@ -417,27 +417,25 @@ public URI getUri() { @Nested class SelectModuleTests { + @SuppressWarnings("DataFlowIssue") @Test - void selectModuleByName() { - var selector = selectModule("java.base"); - assertEquals("java.base", selector.getModuleName()); + void selectModuleByNamePreconditions() { + assertViolatesPrecondition(() -> selectModule(null)); + assertViolatesPrecondition(() -> selectModule("")); + assertViolatesPrecondition(() -> selectModule(" ")); } @Test - void parseModuleByName() { - var selector = parseIdentifier(selectModule("java.base")); - assertThat(selector) // - .asInstanceOf(type(ModuleSelector.class)) // - .extracting(ModuleSelector::getModuleName) // - .isEqualTo("java.base"); + void selectModuleByName() { + var selector = selectModule("java.base"); + assertEquals("java.base", selector.getModuleName()); } @SuppressWarnings("DataFlowIssue") @Test - void selectModuleByNamePreconditions() { - assertViolatesPrecondition(() -> selectModule(null)); - assertViolatesPrecondition(() -> selectModule("")); - assertViolatesPrecondition(() -> selectModule(" ")); + void selectModulesByNamesPreconditions() { + assertViolatesPrecondition(() -> selectModules(null)); + assertViolatesPrecondition(() -> selectModules(Set.of("a", " "))); } @Test @@ -447,11 +445,13 @@ void selectModulesByNames() { assertThat(names).containsExactlyInAnyOrder("b", "a"); } - @SuppressWarnings("DataFlowIssue") @Test - void selectModulesByNamesPreconditions() { - assertViolatesPrecondition(() -> selectModules(null)); - assertViolatesPrecondition(() -> selectModules(Set.of("a", " "))); + void parseModuleSelector() { + var selector = parseIdentifier(selectModule("java.base")); + assertThat(selector) // + .asInstanceOf(type(ModuleSelector.class)) // + .extracting(ModuleSelector::getModuleName) // + .isEqualTo("java.base"); } } @@ -466,7 +466,7 @@ void selectPackageByName() { } @Test - void parsePackageByName() { + void parsePackageSelector() { var selector = parseIdentifier(selectPackage(getClass().getPackage().getName())); assertThat(selector) // .asInstanceOf(type(PackageSelector.class)) // @@ -510,6 +510,41 @@ void selectClasspathRootsWithExistingJarFile() throws Exception { assertThat(selectors).extracting(ClasspathRootSelector::getClasspathRoot).containsExactly(jarUri); } + @Test + void parseClasspathRootSelectorWithNonExistingDirectory() { + var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(Path.of("some/local/path")))); + assertThat(selectorStream).isEmpty(); + } + + @Test + void parseClasspathRootSelectorWithNonExistingJarFile() { + var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(Path.of("some.jar")))); + assertThat(selectorStream).isEmpty(); + } + + @Test + void parseClasspathRootSelectorWithExistingDirectory(@TempDir Path tempDir) { + var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(tempDir))); + var selector = selectorStream.findAny().orElseThrow(); + assertThat(selector) // + .asInstanceOf(type(ClasspathRootSelector.class)) // + .extracting(ClasspathRootSelector::getClasspathRoot) // + .isEqualTo(tempDir.toUri()); + } + + @Test + void parseClasspathRootSelectorWithExistingJarFile() throws Exception { + var jarUri = requireNonNull(getClass().getResource("/jartest.jar")).toURI(); + var jarPath = Path.of(jarUri); + + var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(jarPath))); + var selector = selectorStream.findAny().orElseThrow(); + assertThat(selector) // + .asInstanceOf(type(ClasspathRootSelector.class)) // + .extracting(ClasspathRootSelector::getClasspathRoot) // + .isEqualTo(jarUri); + } + } @Nested @@ -1062,41 +1097,6 @@ private static Class testClass() { } - @Test - void parseClasspathRootsWithNonExistingDirectory() { - var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(Path.of("some/local/path")))); - assertThat(selectorStream).isEmpty(); - } - - @Test - void parseClasspathRootsWithNonExistingJarFile() { - var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(Path.of("some.jar")))); - assertThat(selectorStream).isEmpty(); - } - - @Test - void parseClasspathRootsWithExistingDirectory(@TempDir Path tempDir) { - var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(tempDir))); - var selector = selectorStream.findAny().orElseThrow(); - assertThat(selector) // - .asInstanceOf(type(ClasspathRootSelector.class)) // - .extracting(ClasspathRootSelector::getClasspathRoot) // - .isEqualTo(tempDir.toUri()); - } - - @Test - void parseClasspathRootsWithExistingJarFile() throws Exception { - var jarUri = requireNonNull(getClass().getResource("/jartest.jar")).toURI(); - var jarPath = Path.of(jarUri); - - var selectorStream = parseIdentifiers(selectClasspathRoots(Set.of(jarPath))); - var selector = selectorStream.findAny().orElseThrow(); - assertThat(selector) // - .asInstanceOf(type(ClasspathRootSelector.class)) // - .extracting(ClasspathRootSelector::getClasspathRoot) // - .isEqualTo(jarUri); - } - @Nested class SelectNestedClassAndSelectNestedMethodTests { @@ -1413,6 +1413,7 @@ void doubleNestedTest() { @Nested class SelectIterationTests { + @Test void selectsIteration() throws Exception { Class clazz = DiscoverySelectorsTests.class; @@ -1423,16 +1424,19 @@ void selectsIteration() throws Exception { assertThat(selector.getIterationIndices()).containsExactly(23, 42); assertThat(parseIdentifier(selector)).isEqualTo(selector); } + } @Nested class SelectUniqueIdTests { + @Test void selectsUniqueId() { var selector = selectUniqueId(uniqueIdForMethod(DiscoverySelectorsTests.class, "myTest(int)")); assertThat(selector.getUniqueId()).isNotNull(); assertThat(parseIdentifier(selector)).isEqualTo(selector); } + } // ------------------------------------------------------------------------- From 143fb45b7be4e2939906b8d3d17b1b9d5569bd0a Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:38:36 +0200 Subject: [PATCH 15/33] Polishing --- .../engine/AdditionalDiscoverySelectors.java | 3 +-- .../discovery/DiscoverySelectorsTests.java | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java index 2c00b7f90c85..f2ed0327bd60 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java @@ -114,8 +114,7 @@ static ClasspathResourceSelector selectClasspathResource(String classpathResourc } static List parseIdentifiers(String[] identifiers) { - return DiscoverySelectors.parseAll(identifiers) // - .toList(); + return DiscoverySelectors.parseAll(identifiers).toList(); } private static Stream uniqueStreamOf(T[] elements) { diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java index 36808926fe37..7a220c4aaa78 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java @@ -551,18 +551,15 @@ void parseClasspathRootSelectorWithExistingJarFile() throws Exception { class SelectClassTests { @Test - void selectClassByName() { - var selector = selectClass(getClass().getName()); + void selectClassByReference() { + var selector = selectClass(getClass()); assertEquals(getClass(), selector.getJavaClass()); } @Test - void pareClassByName() { - var selector = parseIdentifier(selectClass(getClass())); - assertThat(selector) // - .asInstanceOf(type(ClassSelector.class)) // - .extracting(ClassSelector::getJavaClass) // - .isEqualTo(getClass()); + void selectClassByName() { + var selector = selectClass(getClass().getName()); + assertEquals(getClass(), selector.getJavaClass()); } @Test @@ -577,6 +574,15 @@ void selectClassByNameWithExplicitClassLoader() throws Exception { } } + @Test + void parseClassSelector() { + var selector = parseIdentifier(selectClass(getClass())); + assertThat(selector) // + .asInstanceOf(type(ClassSelector.class)) // + .extracting(ClassSelector::getJavaClass) // + .isEqualTo(getClass()); + } + } @Nested From 644cdb925ec1f3b000621129c0084f3db54742bb Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:16:54 +0200 Subject: [PATCH 16/33] Create initial 6.0.0 RC2 release notes from template NOTE: this commit also temporarily comments out inclusion of the release notes for 6.0 GA. --- .../docs/asciidoc/release-notes/index.adoc | 4 +- .../release-notes-6.0.0-RC2.adoc | 75 +++++++++++++++++++ .../release-notes/release-notes-6.0.0.adoc | 1 + 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index c99a62643765..2bf7a51d3311 100644 --- a/documentation/src/docs/asciidoc/release-notes/index.adoc +++ b/documentation/src/docs/asciidoc/release-notes/index.adoc @@ -17,7 +17,9 @@ authors as well as build tool and IDE vendors. include::{includedir}/link-attributes.adoc[] -include::{basedir}/release-notes-6.0.0.adoc[] +// include::{basedir}/release-notes-6.0.0.adoc[] + +include::{basedir}/release-notes-6.0.0-RC2.adoc[] include::{basedir}/release-notes-6.0.0-RC1.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc new file mode 100644 index 000000000000..ae181dc4cbe0 --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -0,0 +1,75 @@ +[[release-notes-6.0.0-RC2]] +== 6.0.0-RC2 + +*Date of Release:* ❓ + +*Scope:* Minor enhancements and bug fixes since 6.0.0-RC1. + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit-framework-repo}+/milestone/105?closed=1+[6.0.0-RC2] milestone page in the +JUnit repository on GitHub. + +[TIP] +.Migration Guide +==== +Please refer to the +https://github.com/junit-team/junit-framework/wiki/Upgrading-to-JUnit-6.0[wiki] for +guidance on upgrading from JUnit 5.x.y to 6.0.0. +==== + + +[[release-notes-6.0.0-RC2-junit-platform]] +=== JUnit Platform + +[[release-notes-6.0.0-RC2-junit-platform-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-RC2-junit-platform-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-RC2-junit-platform-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-6.0.0-RC2-junit-jupiter]] +=== JUnit Jupiter + +[[release-notes-6.0.0-RC2-junit-jupiter-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-RC2-junit-jupiter-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-RC2-junit-jupiter-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-6.0.0-RC2-junit-vintage]] +=== JUnit Vintage + +[[release-notes-6.0.0-RC2-junit-vintage-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-RC2-junit-vintage-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-RC2-junit-vintage-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc index 825ab588bb2d..67f92bbe6414 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc @@ -17,6 +17,7 @@ https://github.com/junit-team/junit-framework/wiki/Upgrading-to-JUnit-6.0[wiki] guidance on upgrading from JUnit 5.x.y to 6.0.0. ==== + [[release-notes-6.0.0-junit-platform]] === JUnit Platform From d41ef32a9b36b91360855960e2312de1e3cee5c1 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:38:36 +0200 Subject: [PATCH 17/33] Consistently use array() utility in CsvArgumentsProviderTests --- .../params/provider/CsvArgumentsProviderTests.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java index 2b92d620cfc9..5358715a9c10 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java @@ -115,7 +115,7 @@ void trimsLeadingSpaces() { var arguments = provideArguments(annotation); - assertThat(arguments).containsExactly(new Object[][] { { "", "1" }, { "", "2" }, { "", "3" }, { "", "4" } }); + assertThat(arguments).containsExactly(array("", "1"), array("", "2"), array("", "3"), array("", "4")); } @Test @@ -124,7 +124,7 @@ void trimsTrailingSpaces() { var arguments = provideArguments(annotation); - assertThat(arguments).containsExactly(new Object[][] { { "1", "" }, { "2", "" }, { "3", "" }, { "4", "" } }); + assertThat(arguments).containsExactly(array("1", ""), array("2", ""), array("3", ""), array("4", "")); } @Test @@ -159,8 +159,7 @@ void ignoresLeadingAndTrailingSpaces() { var arguments = provideArguments(annotation); - assertThat(arguments).containsExactly( - new Object[][] { { "1", "a" }, { "2", " b" }, { "3", "c " }, { "4", " d " } }); + assertThat(arguments).containsExactly(array("1", "a"), array("2", " b"), array("3", "c "), array("4", " d ")); } @Test @@ -293,9 +292,7 @@ void customNullValueInHeader() { apple, 1 """).build(); - assertThat(headersToValues(annotation)).containsExactly(// - array("FRUIT = apple", "null = 1")// - ); + assertThat(headersToValues(annotation)).containsExactly(array("FRUIT = apple", "null = 1")); } @Test @@ -304,7 +301,7 @@ void convertsEmptyValuesToNullInLinesAfterFirstLine() { var arguments = provideArguments(annotation); - assertThat(arguments).containsExactly(new Object[][] { { "", "" }, { null, null } }); + assertThat(arguments).containsExactly(array("", ""), array(null, null)); } @Test From 91ae0269f0c61e8f61f1a1c507816eefb40d4b9f Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:14:35 +0200 Subject: [PATCH 18/33] Further improve trim vs. strip tests See commit 2a52a0643fba15b52fcf13dd553758fcbc1d0458 See commit 24b3c407e9a3640cf3003b7241e1e1378c7c6e89 See #3824 --- .../provider/CsvArgumentsProviderTests.java | 82 +++++++++++++------ 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java index 5358715a9c10..686cac19cf4e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java @@ -109,18 +109,24 @@ void splitsAndTrimsArguments() { assertThat(arguments).containsExactly(array("foo", "bar")); } + /** + * @see GitHub issue #3824 + */ @Test - void trimsLeadingSpaces() { - var annotation = csvSource("'', 1", " '', 2", "'' , 3", " '' , 4"); + void trimsLeadingWhitespaceAndControlCharacters() { + var annotation = csvSource("'', 1", "\t'',\b2", "'',\u00003", " '', \t 4"); var arguments = provideArguments(annotation); assertThat(arguments).containsExactly(array("", "1"), array("", "2"), array("", "3"), array("", "4")); } + /** + * @see GitHub issue #3824 + */ @Test - void trimsTrailingSpaces() { - var annotation = csvSource("1,''", "2, ''", "3,'' ", "4, '' "); + void trimsTrailingWhitespaceAndControlCharacters() { + var annotation = csvSource("1 ,'' ", "2\t,''\b", "3 ,''\u0000", "4,'' \t "); var arguments = provideArguments(annotation); @@ -128,38 +134,62 @@ void trimsTrailingSpaces() { } @Test - void trimsSpacesUsingStringTrim() { - // \u0000 (null) removed by trim(), preserved by strip() + void preservesLeadingAndTrailingWhitespaceAndControlCharactersWhenRequested() { + var annotation = csvSource().lines(" 1 , a ", "\t2\b, b ", "\u00003\u0007,c ", "4, \t d \t ") // + .ignoreLeadingAndTrailingWhitespace(false).build(); + + var arguments = provideArguments(annotation); + + assertThat(arguments).containsExactly(// + array(" 1 ", " a "), // + array("\t2\b", " b "), // + array("\u00003\u0007", "c "), // + array("4", " \t d \t ")); + } + + /** + * @see GitHub issue #3824 + */ + @Test + void trimVsStripSemanticsWithUnquotedText() { + // \u0000 (null character) removed by trim(), preserved by strip() // \u00A0 (non-breaking space) preserved by trim(), removed by strip() - var annotation = csvSource().lines( - // Unquoted - "\u0000, \u0000foo\u0000, \u00A0bar\u00A0", - // Quoted - "'\u0000', '\u0000 foo \u0000', ' \u00A0bar\u0000'", - // Mixed - "\u0000'\u0000 foo', \u00A0' bar\u0000'"// - ).build(); + + var annotation = csvSource().lines("\u0000, \u0000foo\u0000, \u00A0bar\u00A0").build(); var arguments = provideArguments(annotation); - assertThat(arguments).containsExactly( - // Unquoted - array("", "foo", "\u00A0bar\u00A0"), - // Quoted - array("\u0000", "\u0000 foo \u0000", " \u00A0bar\u0000"), - // Mixed - array("\u0000 foo", "\u00A0' bar\u0000'")// - ); + assertThat(arguments).containsExactly(array("", "foo", "\u00A0bar\u00A0")); } + /** + * @see GitHub issue #3824 + */ @Test - void ignoresLeadingAndTrailingSpaces() { - var annotation = csvSource().lines("1,a", "2, b", "3,c ", "4, d ") // - .ignoreLeadingAndTrailingWhitespace(false).build(); + void trimVsStripSemanticsWithQuotedText() { + // \u0000 (null character) removed by trim(), preserved by strip() + // \u00A0 (non-breaking space) preserved by trim(), removed by strip() + + var annotation = csvSource().lines("'\u0000', '\u0000 foo \u0000', '\t\u00A0bar\u0000'").build(); + + var arguments = provideArguments(annotation); + + assertThat(arguments).containsExactly(array("\u0000", "\u0000 foo \u0000", "\t\u00A0bar\u0000")); + } + + /** + * @see GitHub issue #3824 + */ + @Test + void trimVsStripSemanticsWithUnquotedAndQuotedText() { + // \u0000 (null character) removed by trim(), preserved by strip() + // \u00A0 (non-breaking space) preserved by trim(), removed by strip() + + var annotation = csvSource().lines("\u0000'\u0000 foo', \u00A0' bar\u0000'").build(); var arguments = provideArguments(annotation); - assertThat(arguments).containsExactly(array("1", "a"), array("2", " b"), array("3", "c "), array("4", " d ")); + assertThat(arguments).containsExactly(array("\u0000 foo", "\u00A0' bar\u0000'")); } @Test From a400fc6c3ff1899c2bc0e2bf350b338b55364d02 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 22 Aug 2025 18:34:41 +0200 Subject: [PATCH 19/33] Retain original TestEngine order after pruning Prior to this commit, LauncherDiscoveryResult.retainEngines() stored the retained LinkedHashMap content in a HashMap, which sometimes resulted in different iteration order if test engines were pruned. To address that, this commit replaces the use of the Stream API and Collectors.toMap() (which creates a HashMap) -- with the use of a LinkedHashMap combined with entrySet().removeIf() which allows us to ensure that the retained test engines are stored in a LinkedHashMap that maintains the original iteration order. Fixes #4862 Closes #4864 --- .../release-notes-6.0.0-RC2.adoc | 4 +- .../core/LauncherDiscoveryResult.java | 10 +- .../core/LauncherDiscoveryResultTests.java | 111 ++++++++++++++++++ 3 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc index ae181dc4cbe0..36eb3a5d93d5 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -24,7 +24,9 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. [[release-notes-6.0.0-RC2-junit-platform-bug-fixes]] ==== Bug Fixes -* ❓ +* The `Launcher` (specifically `LauncherDiscoveryResult`) now retains the original + `TestEngine` registration order after pruning test engines without tests, thereby + ensuring reliable test execution order of multiple test engines. [[release-notes-6.0.0-RC2-junit-platform-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java index 6827cd0246a0..2510a43a5f5c 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java @@ -12,7 +12,6 @@ import static java.util.Collections.unmodifiableMap; import static java.util.Objects.requireNonNull; -import static java.util.stream.Collectors.toMap; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Collection; @@ -96,12 +95,9 @@ public LauncherDiscoveryResult withRetainedEngines(Predicate retainEngines(Predicate predicate) { - // @formatter:off - return this.testEngineResults.entrySet() - .stream() - .filter(entry -> predicate.test(entry.getValue().getRootDescriptor())) - .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); - // @formatter:on + var retainedEngines = new LinkedHashMap<>(this.testEngineResults); + retainedEngines.entrySet().removeIf(entry -> !predicate.test(entry.getValue().getRootDescriptor())); + return retainedEngines; } static class EngineResultInfo { diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java new file mode 100644 index 000000000000..b3545351bf6b --- /dev/null +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher.core; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.platform.engine.EngineDiscoveryRequest; +import org.junit.platform.engine.ExecutionRequest; +import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.TestEngine; +import org.junit.platform.engine.UniqueId; +import org.junit.platform.launcher.core.LauncherDiscoveryResult.EngineResultInfo; + +/** + * Unit tests for {@link LauncherDiscoveryResult}. + */ +class LauncherDiscoveryResultTests { + + /** + * @see GitHub issue #4862 + */ + @Test + void withRetainedEnginesRetainsLinkedHashMapSemantics() { + TestEngine engine1 = new DummyEngine1(); + TestEngine engine2 = new DummyEngine2(); + TestEngine engine3 = new DummyEngine3(); + TestEngine engine4 = new DummyEngine4(); + + TestDescriptor rootDescriptor1 = mock(); + TestDescriptor rootDescriptor2 = mock(); + TestDescriptor rootDescriptor3 = mock(); + TestDescriptor rootDescriptor4 = mock(); + when(rootDescriptor1.isTest()).thenReturn(true); + when(rootDescriptor2.isTest()).thenReturn(false); + when(rootDescriptor3.isTest()).thenReturn(false); + when(rootDescriptor4.isTest()).thenReturn(true); + + EngineResultInfo engineResultInfo1 = mock(); + EngineResultInfo engineResultInfo2 = mock(); + EngineResultInfo engineResultInfo3 = mock(); + EngineResultInfo engineResultInfo4 = mock(); + when(engineResultInfo1.getRootDescriptor()).thenReturn(rootDescriptor1); + when(engineResultInfo2.getRootDescriptor()).thenReturn(rootDescriptor2); + when(engineResultInfo3.getRootDescriptor()).thenReturn(rootDescriptor3); + when(engineResultInfo4.getRootDescriptor()).thenReturn(rootDescriptor4); + + @SuppressWarnings("serial") + Map engineResults = new LinkedHashMap<>() { + { + put(engine1, engineResultInfo1); + put(engine2, engineResultInfo2); + put(engine3, engineResultInfo3); + put(engine4, engineResultInfo4); + } + }; + + assertThat(engineResults.keySet()).containsExactly(engine1, engine2, engine3, engine4); + + LauncherDiscoveryResult discoveryResult = new LauncherDiscoveryResult(engineResults, mock(), mock()); + assertThat(discoveryResult.getTestEngines()).containsExactly(engine1, engine2, engine3, engine4); + + LauncherDiscoveryResult withRetainedEngines = discoveryResult.withRetainedEngines(TestDescriptor::isTest); + + assertThat(withRetainedEngines.getTestEngines()).containsExactly(engine1, engine4); + } + + private static abstract class AbstractDummyEngine implements TestEngine { + + @Override + public String getId() { + return getClass().getSimpleName(); + } + + @Override + public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { + throw new UnsupportedOperationException("discover"); + } + + @Override + public void execute(ExecutionRequest request) { + throw new UnsupportedOperationException("execute"); + } + } + + private static class DummyEngine1 extends AbstractDummyEngine { + } + + private static class DummyEngine2 extends AbstractDummyEngine { + } + + private static class DummyEngine3 extends AbstractDummyEngine { + } + + private static class DummyEngine4 extends AbstractDummyEngine { + } + +} From 68691777bb7915059de3a9be92bab75ee615389a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 22:47:45 +0000 Subject: [PATCH 20/33] Update github/codeql-action action to v3.29.11 (#4861) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/ossf-scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a807fc1f193d..80c52be27309 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -45,7 +45,7 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@96f518a34f7a870018057716cc4d7a5c014bd61c # v3.29.10 + uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -60,6 +60,6 @@ jobs: -Dscan.tag.CodeQL \ classes - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@96f518a34f7a870018057716cc4d7a5c014bd61c # v3.29.10 + uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index aff0daa67eaa..b158dbe3e984 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -57,6 +57,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@96f518a34f7a870018057716cc4d7a5c014bd61c # v3.29.10 + uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 with: sarif_file: results.sarif From 0527706eb961ba9f57e7576c12885c5594908548 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sat, 23 Aug 2025 14:29:22 +0200 Subject: [PATCH 21/33] Introduce selectClasses*() variants in DiscoverySelectors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to this commit, it was possible to select multiple classes by invoking selectClass() multiple times; however, it could become a bit verbose as in the following example. EngineTestKit.engine("junit-jupiter") .selectors( selectClass(TestClass1A.class), selectClass(TestClass1B.class), selectClass(TestClass2A.class), selectClass(TestClass2B.class)) To improve the programming model for users, this commit introduces multiple selectClasses(...) and selectClassesByName(...) variants in DiscoverySelectors. The following example demonstrates use of the new selectClasses(Class...) varargs variant. EngineTestKit.engine("junit-jupiter") .selectors( selectClasses( TestClass1A.class, TestClass1B.class, TestClass2A.class, TestClass2B.class)) In addition, the AdditionalDiscoverySelectors utility used by the @⁠Suite engine no longer needs to implement its own selectClasses(...) utilities. Closes #4860 Closes #4863 --- .../release-notes-6.0.0-RC2.adoc | 4 +- .../engine/discovery/DiscoverySelectors.java | 114 ++++++++++++++++++ .../engine/AdditionalDiscoverySelectors.java | 15 --- .../SuiteLauncherDiscoveryRequestBuilder.java | 4 +- .../testkit/engine/EngineTestKit.java | 22 ++++ .../jupiter/api/RandomlyOrderedTests.java | 4 +- .../AbstractJupiterTestEngineTests.java | 5 + .../engine/StandardTestClassTests.java | 11 +- .../engine/discovery/DiscoveryTests.java | 5 +- .../engine/extension/OrderedClassTests.java | 20 +-- .../extension/TempDirectoryCleanupTests.java | 3 +- .../discovery/DiscoverySelectorsTests.java | 76 ++++++++++++ .../hierarchical/ForkJoinDeadLockTests.java | 6 +- .../ParallelExecutionIntegrationTests.java | 9 +- .../launcher/core/LauncherFactoryTests.java | 4 +- ...queIdTrackingListenerIntegrationTests.java | 10 +- 16 files changed, 261 insertions(+), 51 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc index 36eb3a5d93d5..bab4d9b5d5fb 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -36,7 +36,9 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. [[release-notes-6.0.0-RC2-junit-platform-new-features-and-improvements]] ==== New Features and Improvements -* ❓ +* New `selectClasses(...)` and `selectClassesByName(...)` utility methods have been + introduced in `{DiscoverySelectors}` to simplify use cases where one needs to select + multiple individual test classes for the `Launcher` or `EngineTestKit`. [[release-notes-6.0.0-RC2-junit-jupiter]] diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java index 3cdb8dbf71b3..898fc8574249 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java @@ -10,6 +10,7 @@ package org.junit.platform.engine.discovery; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; @@ -450,6 +451,119 @@ public static ClassSelector selectClass(@Nullable ClassLoader classLoader, Strin return new ClassSelector(classLoader, className); } + /** + * Create a {@code ClassSelector} for each supplied {@link Class}. + * + * @param classes the classes to select; never {@code null} and never containing + * {@code null} class references + * @since 6.0 + * @see #selectClass(Class) + * @see #selectClasses(List) + * @see ClassSelector + */ + @API(status = EXPERIMENTAL, since = "6.0") + public static List selectClasses(Class... classes) { + return selectClasses(List.of(classes)); + } + + /** + * Create a {@code ClassSelector} for each supplied {@link Class}. + * + * @param classes the classes to select; never {@code null} and never containing + * {@code null} class references + * @since 6.0 + * @see #selectClass(Class) + * @see #selectClasses(Class...) + * @see ClassSelector + */ + @API(status = EXPERIMENTAL, since = "6.0") + public static List selectClasses(List> classes) { + Preconditions.notNull(classes, "classes must not be null"); + Preconditions.containsNoNullElements(classes, "Individual classes must not be null"); + + // @formatter:off + return classes.stream() + .distinct() + .map(DiscoverySelectors::selectClass) + .toList(); + // @formatter:on + } + + /** + * Create a {@code ClassSelector} for each supplied class name. + * + * @param classNames the fully qualified names of the classes to select; + * never {@code null} and never containing {@code null} or blank names + * @since 6.0 + * @see #selectClass(String) + * @see #selectClassesByName(List) + * @see #selectClassesByName(ClassLoader, String...) + * @see ClassSelector + */ + @API(status = EXPERIMENTAL, since = "6.0") + public static List selectClassesByName(String... classNames) { + return selectClassesByName(List.of(classNames)); + } + + /** + * Create a {@code ClassSelector} for each supplied class name. + * + * @param classNames the fully qualified names of the classes to select; + * never {@code null} and never containing {@code null} or blank names + * @since 6.0 + * @see #selectClass(String) + * @see #selectClassesByName(String...) + * @see #selectClassesByName(ClassLoader, List) + * @see ClassSelector + */ + @API(status = EXPERIMENTAL, since = "6.0") + public static List selectClassesByName(List classNames) { + return selectClassesByName(null, classNames); + } + + /** + * Create a {@code ClassSelector} for each supplied class name, using the + * supplied class loader. + * + * @param classLoader the class loader to use to load the classes, or {@code null} + * to signal that the default {@code ClassLoader} should be used + * @param classNames the fully qualified names of the classes to select; + * never {@code null} and never containing {@code null} or blank names + * @since 6.0 + * @see #selectClass(ClassLoader, String) + * @see #selectClassesByName(ClassLoader, List) + * @see ClassSelector + */ + @API(status = EXPERIMENTAL, since = "6.0") + public static List selectClassesByName(@Nullable ClassLoader classLoader, String... classNames) { + return selectClassesByName(classLoader, List.of(classNames)); + } + + /** + * Create a {@code ClassSelector} for each supplied class name, using the + * supplied class loader. + * + * @param classLoader the class loader to use to load the classes, or {@code null} + * to signal that the default {@code ClassLoader} should be used + * @param classNames the fully qualified names of the classes to select; + * never {@code null} and never containing {@code null} or blank names + * @since 6.0 + * @see #selectClass(ClassLoader, String) + * @see ClassSelector + */ + @API(status = EXPERIMENTAL, since = "6.0") + public static List selectClassesByName(@Nullable ClassLoader classLoader, List classNames) { + Preconditions.notNull(classNames, "classNames must not be null"); + Preconditions.containsNoNullElements(classNames, "Individual class names must not be null"); + + // @formatter:off + return classNames.stream() + .distinct() + .map(className -> selectClass(classLoader, className)) + .toList(); + // @formatter:on + } + /** * Create a {@code MethodSelector} for the supplied fully qualified * method name. diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java index f2ed0327bd60..e4b8364595ec 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/AdditionalDiscoverySelectors.java @@ -18,7 +18,6 @@ import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.DiscoverySelector; -import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; import org.junit.platform.engine.discovery.DirectorySelector; import org.junit.platform.engine.discovery.DiscoverySelectors; @@ -68,20 +67,6 @@ static List selectPackages(String... packageNames) { // @formatter:on } - static Stream selectClasses(Class... classes) { - Preconditions.notNull(classes, "classes must not be null"); - Preconditions.containsNoNullElements(classes, "Individual classes must not be null"); - - return uniqueStreamOf(classes).map(DiscoverySelectors::selectClass); - } - - static Stream selectClasses(String... classNames) { - Preconditions.notNull(classNames, "classNames must not be null"); - Preconditions.containsNoNullElements(classNames, "Individual class names must not be null"); - - return uniqueStreamOf(classNames).map(DiscoverySelectors::selectClass); - } - static List selectModules(String... moduleNames) { Preconditions.notNull(moduleNames, "Module names must not be null"); Preconditions.containsNoNullElements(moduleNames, "Individual module names must not be null"); diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java index 0f0a4b031ef5..094c08dff9eb 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteLauncherDiscoveryRequestBuilder.java @@ -376,8 +376,8 @@ private static Stream toClassSelectors(Class suiteClass, Selec () -> "@SelectClasses on class [%s] must declare at least one class reference or name".formatted( suiteClass.getName())); return Stream.concat(// - AdditionalDiscoverySelectors.selectClasses(annotation.value()), // - AdditionalDiscoverySelectors.selectClasses(annotation.names()) // + DiscoverySelectors.selectClasses(annotation.value()).stream(), // + DiscoverySelectors.selectClassesByName(annotation.names()).stream() // ); } diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java index b1e840cb7ff8..189395fde0cd 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java @@ -329,6 +329,7 @@ private Builder(TestEngine testEngine) { * * @param selectors the discovery selectors to add; never {@code null} * @return this builder for method chaining + * @see #selectors(List) * @see #filters(Filter...) * @see #configurationParameter(String, String) * @see #configurationParameters(Map) @@ -339,6 +340,27 @@ public Builder selectors(DiscoverySelector... selectors) { return this; } + /** + * Add all of the supplied {@linkplain DiscoverySelector discovery selectors}. + * + *

Built-in discovery selectors can be created via the static factory + * methods in {@link org.junit.platform.engine.discovery.DiscoverySelectors}. + * + * @param selectors the discovery selectors to add; never {@code null} + * @return this builder for method chaining + * @since 6.0 + * @see #selectors(DiscoverySelector...) + * @see #filters(Filter...) + * @see #configurationParameter(String, String) + * @see #configurationParameters(Map) + * @see #execute() + */ + @API(status = MAINTAINED, since = "6.0") + public Builder selectors(List selectors) { + this.requestBuilder.selectors(selectors); + return this; + } + /** * Add all of the supplied {@linkplain Filter filters}. * diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/RandomlyOrderedTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/RandomlyOrderedTests.java index 69ab15fe197b..7ced2604ab53 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/RandomlyOrderedTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/RandomlyOrderedTests.java @@ -13,7 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import java.util.Collections; import java.util.LinkedHashSet; @@ -49,7 +49,7 @@ private Events executeTests(@SuppressWarnings("SameParameterValue") long randomS .configurationParameter(DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME, ClassOrderer.Random.class.getName()) .configurationParameter(DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME, MethodOrderer.Random.class.getName()) .configurationParameter(MethodOrderer.Random.RANDOM_SEED_PROPERTY_NAME, String.valueOf(randomSeed)) - .selectors(selectClass(A_TestCase.class), selectClass(B_TestCase.class), selectClass(C_TestCase.class)) + .selectors(selectClasses(A_TestCase.class, B_TestCase.class, C_TestCase.class)) .execute() .testEvents(); // @formatter:on diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java index 02d084aa65be..0697ea5c6ef7 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java @@ -20,6 +20,7 @@ import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.launcher.core.OutputDirectoryProviders.dummyOutputDirectoryProvider; +import java.util.List; import java.util.function.Consumer; import org.junit.platform.engine.DiscoveryIssue.Severity; @@ -52,6 +53,10 @@ protected EngineExecutionResults executeTestsForClass(Class testClass) { } protected EngineExecutionResults executeTests(DiscoverySelector... selectors) { + return executeTests(List.of(selectors)); + } + + protected EngineExecutionResults executeTests(List selectors) { return executeTests(request -> request.selectors(selectors)); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/StandardTestClassTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/StandardTestClassTests.java index 1d458e174f32..29a3f94a188c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/StandardTestClassTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/StandardTestClassTests.java @@ -14,6 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import org.junit.jupiter.api.AfterEach; @@ -44,16 +45,18 @@ void standardTestClassIsCorrectlyDiscovered() { @Test void moreThanOneTestClassIsCorrectlyDiscovered() { - LauncherDiscoveryRequest request = request().selectors(selectClass(SecondOfTwoTestCases.class)).build(); + LauncherDiscoveryRequest request = // + request().selectors(selectClasses(FirstOfTwoTestCases.class, SecondOfTwoTestCases.class)).build(); + TestDescriptor engineDescriptor = discoverTests(request).getEngineDescriptor(); - assertEquals(1 /*class*/ + 3 /*methods*/, engineDescriptor.getDescendants().size(), + assertEquals(2 /*class*/ + 6 /*methods*/, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @Test void moreThanOneTestClassIsExecuted() { - LauncherDiscoveryRequest request = request().selectors(selectClass(FirstOfTwoTestCases.class), - selectClass(SecondOfTwoTestCases.class)).build(); + LauncherDiscoveryRequest request = // + request().selectors(selectClasses(FirstOfTwoTestCases.class, SecondOfTwoTestCases.class)).build(); EngineExecutionResults executionResults = executeTests(request); Events containers = executionResults.containerEvents(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java index 02fa1eb5b01d..0f51f95508d4 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java @@ -22,6 +22,7 @@ import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectNestedClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectNestedMethod; @@ -254,8 +255,8 @@ static List> requestsForTestClassWithInvalidTest .filters(includeClassNamePatterns( Pattern.quote(InvalidTestCases.InvalidTestMethodTestCase.class.getName()))).build()), // named("subclasses", defaultRequest() // - .selectors(selectClass(InvalidTestCases.InvalidTestMethodSubclass1TestCase.class), - selectClass(InvalidTestCases.InvalidTestMethodSubclass2TestCase.class)) // + .selectors(selectClasses(InvalidTestCases.InvalidTestMethodSubclass1TestCase.class, + InvalidTestCases.InvalidTestMethodSubclass2TestCase.class)) // .build()) // ); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java index 57ed8072bfa3..f3b0d8b429a6 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java @@ -14,6 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import java.util.ArrayList; import java.util.Collections; @@ -93,7 +94,7 @@ void classNameAcrossPackages() { example.B_TestCase.callSequence = callSequence; // @formatter:off - executeTests(ClassOrderer.ClassName.class, selectClass(B_TestCase.class), selectClass(example.B_TestCase.class)) + executeTests(ClassOrderer.ClassName.class, selectClasses(B_TestCase.class, example.B_TestCase.class)) .assertStatistics(stats -> stats.succeeded(callSequence.size())); // @formatter:on @@ -193,7 +194,7 @@ void classTemplateWithGlobalConfig() { var classTemplate = ClassTemplateWithLocalConfigTestCase.class; var otherClass = A_TestCase.class; - executeTests(ClassOrderer.OrderAnnotation.class, selectClass(otherClass), selectClass(classTemplate))// + executeTests(ClassOrderer.OrderAnnotation.class, selectClasses(otherClass, classTemplate))// .assertStatistics(stats -> stats.succeeded(callSequence.size())); assertThat(callSequence)// @@ -231,11 +232,15 @@ private static void assertIneffectiveOrderAnnotationIssues(List } private Events executeTests(@Nullable Class classOrderer) { - return executeTests(classOrderer, selectClass(A_TestCase.class), selectClass(B_TestCase.class), - selectClass(C_TestCase.class)); + return executeTests(classOrderer, selectClasses(A_TestCase.class, B_TestCase.class, C_TestCase.class)); } private Events executeTests(@Nullable Class classOrderer, DiscoverySelector... selectors) { + return executeTests(classOrderer, List.of(selectors)); + } + + private Events executeTests(@Nullable Class classOrderer, + List selectors) { // @formatter:off return testKit(classOrderer, selectors) .execute() @@ -244,17 +249,16 @@ private Events executeTests(@Nullable Class classOrderer } private EngineDiscoveryResults discoverTests(@Nullable Class classOrderer) { - return discoverTests(classOrderer, selectClass(A_TestCase.class), selectClass(B_TestCase.class), - selectClass(C_TestCase.class)); + return discoverTests(classOrderer, selectClasses(A_TestCase.class, B_TestCase.class, C_TestCase.class)); } private EngineDiscoveryResults discoverTests(@Nullable Class classOrderer, - DiscoverySelector... selectors) { + List selectors) { return testKit(classOrderer, selectors).discover(); } private static EngineTestKit.Builder testKit(@Nullable Class classOrderer, - DiscoverySelector[] selectors) { + List selectors) { var testKit = EngineTestKit.engine("junit-jupiter"); if (classOrderer != null) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java index 5619832335ba..1a6f5eecae72 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java @@ -18,6 +18,7 @@ import static org.junit.jupiter.api.io.CleanupMode.NEVER; import static org.junit.jupiter.api.io.CleanupMode.ON_SUCCESS; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; @@ -157,7 +158,7 @@ void cleanupModeOnSuccessFailingField() { @Test void cleanupModeOnSuccessFailingThenPassingField() { - executeTests(selectClass(OnSuccessFailingFieldCase.class), selectClass(OnSuccessPassingFieldCase.class)); + executeTests(selectClasses(OnSuccessFailingFieldCase.class, OnSuccessPassingFieldCase.class)); assertThat(onSuccessFailingFieldDir).exists(); assertThat(onSuccessPassingFieldDir).doesNotExist(); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java index 7a220c4aaa78..87164068f2a9 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java @@ -20,6 +20,8 @@ import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForMethod; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClassesByName; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathResource; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathRoots; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectDirectory; @@ -585,6 +587,80 @@ void parseClassSelector() { } + /** + * @since 6.0 + */ + @Nested + class SelectClassesTests { + + @Test + void selectClassesByReferenceViaVarargs() { + assertSelectClassesByReferenceResults(selectClasses(String.class, Integer.class)); + } + + @Test + void selectClassesByReferenceViaList() { + assertSelectClassesByReferenceResults(selectClasses(List.of(String.class, Integer.class))); + } + + private static void assertSelectClassesByReferenceResults(List selectors) { + Class class1 = String.class; + Class class2 = Integer.class; + + assertThat(selectors).satisfiesExactly(// + selector1 -> { + assertThat(selector1.getJavaClass()).isEqualTo(class1); + assertThat(selector1.getClassName()).isEqualTo(class1.getName()); + }, // + selector2 -> { + assertThat(selector2.getJavaClass()).isEqualTo(class2); + assertThat(selector2.getClassName()).isEqualTo(class2.getName()); + }); + + } + + @Test + void selectClassesByNameViaVarargsWithExplicitClassLoader() throws Exception { + Class class1 = Foo.class; + Class class2 = Bar.class; + + try (var testClassLoader = TestClassLoader.forClasses(class1, class2)) { + assertThat(selectClassesByName(testClassLoader, class1.getName(), class2.getName())).satisfiesExactly( + selector1 -> checkClassSelector(testClassLoader, selector1, class1), // + selector2 -> checkClassSelector(testClassLoader, selector2, class2)); // + } + } + + @Test + void selectClassesByNameViaListWithExplicitClassLoader() throws Exception { + Class class1 = Foo.class; + Class class2 = Bar.class; + + try (var testClassLoader = TestClassLoader.forClasses(class1, class2)) { + assertThat(selectClassesByName(testClassLoader, List.of(class1.getName(), class2.getName())))// + .satisfiesExactly(// + selector1 -> checkClassSelector(testClassLoader, selector1, class1), // + selector2 -> checkClassSelector(testClassLoader, selector2, class2)); // + } + } + + private static void checkClassSelector(TestClassLoader testClassLoader, ClassSelector selector, + Class clazz) { + + assertThat(selector.getJavaClass().getName()).isEqualTo(clazz.getName()); + assertThat(selector.getJavaClass()).isNotEqualTo(clazz); + assertThat(selector.getJavaClass().getClassLoader()).isSameAs(testClassLoader); + assertThat(selector.getClassLoader()).isSameAs(testClassLoader); + } + + class Foo { + } + + class Bar { + } + + } + @Nested class SelectMethodTests { diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinDeadLockTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinDeadLockTests.java index 81afa0225570..1df6e43eb0b0 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinDeadLockTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinDeadLockTests.java @@ -15,9 +15,9 @@ import static org.junit.jupiter.api.parallel.ResourceAccessMode.READ; import static org.junit.jupiter.api.parallel.ResourceAccessMode.READ_WRITE; import static org.junit.jupiter.api.parallel.Resources.SYSTEM_PROPERTIES; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import java.time.LocalTime; -import java.util.Arrays; import java.util.concurrent.CountDownLatch; import org.junit.jupiter.api.Test; @@ -32,8 +32,6 @@ import org.junit.jupiter.api.parallel.Isolated; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.engine.Constants; -import org.junit.platform.engine.discovery.ClassSelector; -import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.testkit.engine.EngineTestKit; // https://github.com/junit-team/junit-framework/issues/3945 @@ -57,7 +55,7 @@ void multiLevelLocks() { private static void run(Class... classes) { EngineTestKit.engine("junit-jupiter") // - .selectors(Arrays.stream(classes).map(DiscoverySelectors::selectClass).toArray(ClassSelector[]::new)) // + .selectors(selectClasses(classes)) // .configurationParameter(Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, "true") // .configurationParameter(Constants.DEFAULT_PARALLEL_EXECUTION_MODE, "concurrent") // .configurationParameter(Constants.DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME, "concurrent") // diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java index a311559c9cea..624bd58d4d67 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java @@ -25,6 +25,7 @@ import static org.junit.jupiter.engine.Constants.PARALLEL_CONFIG_STRATEGY_PROPERTY_NAME; import static org.junit.jupiter.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_KEY; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.event; @@ -38,7 +39,6 @@ import java.net.URL; import java.net.URLClassLoader; import java.time.Instant; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -69,8 +69,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.discovery.ClassSelector; -import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.testkit.engine.EngineExecutionResults; @@ -556,11 +554,8 @@ private Events executeConcurrently(int parallelism, Class... testClasses) { private EngineExecutionResults executeWithFixedParallelism(int parallelism, Map configParams, Class... testClasses) { - var classSelectors = Arrays.stream(testClasses) // - .map(DiscoverySelectors::selectClass) // - .toArray(ClassSelector[]::new); return EngineTestKit.engine("junit-jupiter") // - .selectors(classSelectors) // + .selectors(selectClasses(testClasses)) // .configurationParameter(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, String.valueOf(true)) // .configurationParameter(PARALLEL_CONFIG_STRATEGY_PROPERTY_NAME, "fixed") // .configurationParameter(PARALLEL_CONFIG_FIXED_PARALLELISM_PROPERTY_NAME, String.valueOf(parallelism)) // diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java index 96ce0271adda..3067356d1951 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.TemporaryClasspathExecutor.withAdditionalClasspathRoot; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses; import static org.junit.platform.launcher.LauncherConstants.DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.ENABLE_LAUNCHER_INTERCEPTORS; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; @@ -461,8 +462,7 @@ private static void withTestServices(Runnable runnable) { private LauncherDiscoveryRequest createLauncherDiscoveryRequestForBothStandardEngineExampleClasses() { // @formatter:off return request() - .selectors(selectClass(JUnit4Example.class)) - .selectors(selectClass(JUnit5Example.class)) + .selectors(selectClasses(JUnit4Example.class, JUnit5Example.class)) .enableImplicitConfigurationParameters(false) .build(); // @formatter:on diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java index e2ed675c0e94..7eee9a519e05 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java @@ -56,6 +56,7 @@ import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.discovery.ClassSelector; +import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; @@ -207,6 +208,10 @@ private List executeTests(Map configurationParameters) { } private List executeTests(Map configurationParameters, ClassSelector... classSelectors) { + return executeTests(configurationParameters, List.of(classSelectors)); + } + + private List executeTests(Map configurationParameters, List classSelectors) { List uniqueIds = new ArrayList<>(); var listener = new TestExecutionListener() { @@ -248,9 +253,8 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult return uniqueIds; } - private static ClassSelector[] selectClasses() { - return new ClassSelector[] { selectClass(TestCase1.class), selectClass(TestCase2.class), - selectClass(DisabledTestCase.class) }; + private static List selectClasses() { + return DiscoverySelectors.selectClasses(TestCase1.class, TestCase2.class, DisabledTestCase.class); } private static Stream findFiles(Path outputDir, String prefix) throws IOException { From c4c251a2af5e5d3fda4e8691ed1da43304e17121 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 24 Aug 2025 15:30:51 +0200 Subject: [PATCH 22/33] Document selectors(List) EngineTestKit builder method in release notes See #4860 --- .../docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc index bab4d9b5d5fb..f12486273586 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -39,6 +39,9 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. * New `selectClasses(...)` and `selectClassesByName(...)` utility methods have been introduced in `{DiscoverySelectors}` to simplify use cases where one needs to select multiple individual test classes for the `Launcher` or `EngineTestKit`. +* New `selectors(List)` builder method for `{EngineTestKit}` which can be used in + conjunction with the new `selectClasses(...)` and `selectClassesByName(...)` methods in + `DiscoverySelectors`. [[release-notes-6.0.0-RC2-junit-jupiter]] From 863846191f786978d1a89e8abb67eeae13d9bf12 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 24 Aug 2025 15:38:43 +0200 Subject: [PATCH 23/33] Link to all GitHub milestones from 6.0.0 release notes --- .../docs/asciidoc/release-notes/release-notes-6.0.0.adoc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc index 67f92bbe6414..5a9dc6092940 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0.adoc @@ -6,8 +6,12 @@ *Scope:* ❓ For a complete list of all _closed_ issues and pull requests for this release, consult the -link:{junit-framework-repo}+/milestone/103?closed=1+[6.0.0] milestone page in the JUnit -repository on GitHub. +link:{junit-framework-repo}+/milestone/87?closed=1+[6.0.0-M1], +link:{junit-framework-repo}+/milestone/99?closed=1+[6.0.0-M2], +link:{junit-framework-repo}+/milestone/102?closed=1+[6.0.0-RC1], +link:{junit-framework-repo}+/milestone/105?closed=1+[6.0.0-RC2], and +link:{junit-framework-repo}+/milestone/103?closed=1+[6.0.0] +milestone pages in the JUnit repository on GitHub. [TIP] .Migration Guide From 270b72285351bd082a7fff36a6cc38ac2e6028b1 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:07:10 +0200 Subject: [PATCH 24/33] Simplify LauncherDiscoveryResultTests See #4862 --- .../core/LauncherDiscoveryResultTests.java | 66 ++++++++----------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java index b3545351bf6b..8ebee102a60f 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryResultTests.java @@ -34,55 +34,35 @@ class LauncherDiscoveryResultTests { * @see GitHub issue #4862 */ @Test - void withRetainedEnginesRetainsLinkedHashMapSemantics() { - TestEngine engine1 = new DummyEngine1(); - TestEngine engine2 = new DummyEngine2(); - TestEngine engine3 = new DummyEngine3(); - TestEngine engine4 = new DummyEngine4(); - - TestDescriptor rootDescriptor1 = mock(); - TestDescriptor rootDescriptor2 = mock(); - TestDescriptor rootDescriptor3 = mock(); - TestDescriptor rootDescriptor4 = mock(); - when(rootDescriptor1.isTest()).thenReturn(true); - when(rootDescriptor2.isTest()).thenReturn(false); - when(rootDescriptor3.isTest()).thenReturn(false); - when(rootDescriptor4.isTest()).thenReturn(true); - - EngineResultInfo engineResultInfo1 = mock(); - EngineResultInfo engineResultInfo2 = mock(); - EngineResultInfo engineResultInfo3 = mock(); - EngineResultInfo engineResultInfo4 = mock(); - when(engineResultInfo1.getRootDescriptor()).thenReturn(rootDescriptor1); - when(engineResultInfo2.getRootDescriptor()).thenReturn(rootDescriptor2); - when(engineResultInfo3.getRootDescriptor()).thenReturn(rootDescriptor3); - when(engineResultInfo4.getRootDescriptor()).thenReturn(rootDescriptor4); + void withRetainedEnginesMaintainsOriginalTestEngineRegistrationOrder() { + var engine1 = new DemoEngine("Engine 1"); + var engine2 = new DemoEngine("Engine 2"); + var engine3 = new DemoEngine("Engine 3"); + var engine4 = new DemoEngine("Engine 4"); @SuppressWarnings("serial") Map engineResults = new LinkedHashMap<>() { { - put(engine1, engineResultInfo1); - put(engine2, engineResultInfo2); - put(engine3, engineResultInfo3); - put(engine4, engineResultInfo4); + put(engine1, new DemoEngineResultInfo(true)); + put(engine2, new DemoEngineResultInfo(false)); + put(engine3, new DemoEngineResultInfo(false)); + put(engine4, new DemoEngineResultInfo(true)); } }; - assertThat(engineResults.keySet()).containsExactly(engine1, engine2, engine3, engine4); LauncherDiscoveryResult discoveryResult = new LauncherDiscoveryResult(engineResults, mock(), mock()); assertThat(discoveryResult.getTestEngines()).containsExactly(engine1, engine2, engine3, engine4); - LauncherDiscoveryResult withRetainedEngines = discoveryResult.withRetainedEngines(TestDescriptor::isTest); - - assertThat(withRetainedEngines.getTestEngines()).containsExactly(engine1, engine4); + LauncherDiscoveryResult prunedDiscoveryResult = discoveryResult.withRetainedEngines(TestDescriptor::isTest); + assertThat(prunedDiscoveryResult.getTestEngines()).containsExactly(engine1, engine4); } - private static abstract class AbstractDummyEngine implements TestEngine { + private record DemoEngine(String id) implements TestEngine { @Override public String getId() { - return getClass().getSimpleName(); + return this.id; } @Override @@ -94,18 +74,24 @@ public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId public void execute(ExecutionRequest request) { throw new UnsupportedOperationException("execute"); } - } - private static class DummyEngine1 extends AbstractDummyEngine { + @Override + public String toString() { + return getId(); + } } - private static class DummyEngine2 extends AbstractDummyEngine { - } + private static class DemoEngineResultInfo extends EngineResultInfo { - private static class DummyEngine3 extends AbstractDummyEngine { - } + DemoEngineResultInfo(boolean isTest) { + super(createRootDescriptor(isTest), mock(), null); + } - private static class DummyEngine4 extends AbstractDummyEngine { + private static TestDescriptor createRootDescriptor(boolean isTest) { + TestDescriptor rootDescriptor = mock(); + when(rootDescriptor.isTest()).thenReturn(isTest); + return rootDescriptor; + } } } From 005daabc51044c5f3e105e4ebc14c34b0ddee5f5 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:12:57 +0200 Subject: [PATCH 25/33] Fix selectClasspathRoots() example in LauncherDiscoveryRequestBuilder DiscoverySelectors.selectClasspathRoots() returns a List and therefore cannot be used alongside any other selectors. --- .../launcher/core/LauncherDiscoveryRequestBuilder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java index 93ab9afa728e..0931f5a6fb75 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java @@ -65,10 +65,12 @@ * selectMethod("org.example.order.OrderTests", "test4"), * selectMethod(OrderTests.class, "test5"), * selectMethod(OrderTests.class, testMethod), - * selectClasspathRoots(Collections.singleton(Paths.get("/my/local/path1"))), * selectUniqueId("unique-id-1"), * selectUniqueId("unique-id-2") * ) + * .selectors( + * selectClasspathRoots(Set.of(Paths.get("/my/local/path1"))) + * ) * .filters( * includeEngines("junit-jupiter", "spek"), * // excludeEngines("junit-vintage"), From d9fce9e288692fcc684a3286b231c22d04b91022 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:36:15 +0200 Subject: [PATCH 26/33] Introduce discoveryRequest() and executionRequest() aliases in builders Prior to this commit, LauncherDiscoveryRequestBuilder.request() and LauncherExecutionRequestBuilder.request() could not both be used via static imports in the same Java source file, since the names conflict. To address that and improve the programming model, this commit introduces discoveryRequest() and executionRequest() aliases in those builders, respectively. Closes #4865 --- .../src/docs/asciidoc/link-attributes.adoc | 1 + .../release-notes-6.0.0-RC2.adoc | 6 +++ .../core/LauncherDiscoveryRequestBuilder.java | 20 +++++++- .../core/LauncherExecutionRequestBuilder.java | 32 ++++++++++++ .../LauncherDiscoveryRequestBuilderTests.java | 50 +++++++++---------- .../launcher/core/LauncherSessionTests.java | 35 ++++++------- 6 files changed, 101 insertions(+), 43 deletions(-) diff --git a/documentation/src/docs/asciidoc/link-attributes.adoc b/documentation/src/docs/asciidoc/link-attributes.adoc index ec6ce1494541..dbf48b97b965 100644 --- a/documentation/src/docs/asciidoc/link-attributes.adoc +++ b/documentation/src/docs/asciidoc/link-attributes.adoc @@ -68,6 +68,7 @@ endif::[] :LauncherDiscoveryRequest: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherDiscoveryRequest.html[LauncherDiscoveryRequest] :LauncherDiscoveryRequestBuilder: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.html[LauncherDiscoveryRequestBuilder] :LauncherExecutionRequest: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherExecutionRequest.html[LauncherExecutionRequest] +:LauncherExecutionRequestBuilder: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/core/LauncherExecutionRequestBuilder.html[LauncherExecutionRequestBuilder] :LauncherFactory: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/core/LauncherFactory.html[LauncherFactory] :LauncherInterceptor: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherInterceptor.html[LauncherInterceptor] :LauncherSession: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherSession.html[LauncherSession] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc index f12486273586..07c238233e27 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -36,6 +36,12 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. [[release-notes-6.0.0-RC2-junit-platform-new-features-and-improvements]] ==== New Features and Improvements +* New `discoveryRequest()` method in `{LauncherDiscoveryRequestBuilder}`, which is an + alias for the existing `request()` method and is intended to be used via a `static` + import. +* New `executionRequest(...)` methods in `{LauncherExecutionRequestBuilder}`, which are + aliases for the existing `request(...)` methods and are intended to be used via a + `static` import. * New `selectClasses(...)` and `selectClassesByName(...)` utility methods have been introduced in `{DiscoverySelectors}` to simplify use cases where one needs to select multiple individual test classes for the `Launcher` or `EngineTestKit`. diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java index 0931f5a6fb75..a82a6cc928e0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java @@ -51,10 +51,11 @@ * import static org.junit.platform.engine.discovery.ClassNameFilter.*; * import static org.junit.platform.launcher.EngineFilter.*; * import static org.junit.platform.launcher.TagFilter.*; + * import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.discoveryRequest; * * // ... * - * LauncherDiscoveryRequestBuilder.request() + * discoveryRequest() * .selectors( * selectPackage("org.example.user"), * selectClass("org.example.payment.PaymentTests"), @@ -122,11 +123,28 @@ public final class LauncherDiscoveryRequestBuilder { * Create a new {@code LauncherDiscoveryRequestBuilder}. * * @return a new builder + * @see #discoveryRequest() */ public static LauncherDiscoveryRequestBuilder request() { return new LauncherDiscoveryRequestBuilder(); } + /** + * Create a new {@code LauncherDiscoveryRequestBuilder}. + * + *

This method is an alias for {@link #request()} and is intended + * to be used when statically imported — for example, via: + * {@code import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.discoveryRequest;} + * + * @return a new builder + * @since 6.0 + * @see #request() + */ + @API(status = STABLE, since = "6.0") + public static LauncherDiscoveryRequestBuilder discoveryRequest() { + return request(); + } + private LauncherDiscoveryRequestBuilder() { } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherExecutionRequestBuilder.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherExecutionRequestBuilder.java index 161800c6aeca..a9066cff5a4f 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherExecutionRequestBuilder.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherExecutionRequestBuilder.java @@ -41,23 +41,55 @@ public final class LauncherExecutionRequestBuilder { * {@link LauncherDiscoveryRequest}. * * @return a new builder + * @see #executionRequest(LauncherDiscoveryRequest) */ public static LauncherExecutionRequestBuilder request(LauncherDiscoveryRequest discoveryRequest) { Preconditions.notNull(discoveryRequest, "LauncherDiscoveryRequest must not be null"); return new LauncherExecutionRequestBuilder(discoveryRequest, null); } + /** + * Create a new {@code LauncherExecutionRequestBuilder} from the supplied + * {@link LauncherDiscoveryRequest}. + * + *

This method is an alias for {@link #request(LauncherDiscoveryRequest)} + * and is intended to be used when statically imported — for example, via: + * {@code import static org.junit.platform.launcher.core.LauncherExecutionRequestBuilder.executionRequest;} + * + * @return a new builder + * @see #request(LauncherDiscoveryRequest) + */ + public static LauncherExecutionRequestBuilder executionRequest(LauncherDiscoveryRequest discoveryRequest) { + return request(discoveryRequest); + } + /** * Create a new {@code LauncherExecutionRequestBuilder} from the supplied * {@link TestPlan}. * * @return a new builder + * @see #executionRequest(TestPlan) */ public static LauncherExecutionRequestBuilder request(TestPlan testPlan) { Preconditions.notNull(testPlan, "TestPlan must not be null"); return new LauncherExecutionRequestBuilder(null, testPlan); } + /** + * Create a new {@code LauncherExecutionRequestBuilder} from the supplied + * {@link TestPlan}. + * + *

This method is an alias for {@link #request(TestPlan)} + * and is intended to be used when statically imported — for example, via: + * {@code import static org.junit.platform.launcher.core.LauncherExecutionRequestBuilder.executionRequest;} + * + * @return a new builder + * @see #request(TestPlan) + */ + public static LauncherExecutionRequestBuilder executionRequest(TestPlan testPlan) { + return request(testPlan); + } + private final @Nullable LauncherDiscoveryRequest discoveryRequest; private final @Nullable TestPlan testPlan; private final Collection executionListeners = new ArrayList<>(); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilderTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilderTests.java index 0d92aee8927a..fa8d42498dbb 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilderTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilderTests.java @@ -21,7 +21,7 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME; -import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; +import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.discoveryRequest; import static org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners.abortOnFailure; import static org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners.logging; @@ -56,7 +56,7 @@ class DiscoverySelectionTests { @Test void modulesAreStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = LauncherDiscoveryRequestBuilder.request() .selectors( selectModule("java.base") ).build(); @@ -70,7 +70,7 @@ void modulesAreStoredInDiscoveryRequest() { @Test void packagesAreStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .selectors( selectPackage("org.junit.platform.engine") ).build(); @@ -84,7 +84,7 @@ void packagesAreStoredInDiscoveryRequest() { @Test void classesAreStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .selectors( selectClass(LauncherDiscoveryRequestBuilderTests.class.getName()), selectClass(SampleTestClass.class) @@ -101,7 +101,7 @@ void classesAreStoredInDiscoveryRequest() { @Test void methodsByFullyQualifiedNameAreStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .selectors(selectMethod(fullyQualifiedMethodName())) .build(); // @formatter:on @@ -120,7 +120,7 @@ void methodsByNameAreStoredInDiscoveryRequest() throws Exception { var testMethod = testClass.getDeclaredMethod("test"); // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .selectors(selectMethod(SampleTestClass.class.getName(), "test")) .build(); // @formatter:on @@ -139,7 +139,7 @@ void methodsByClassAreStoredInDiscoveryRequest() throws Exception { var testMethod = testClass.getDeclaredMethod("test"); // @formatter:off - var discoveryRequest = (DefaultDiscoveryRequest) request() + var discoveryRequest = (DefaultDiscoveryRequest) discoveryRequest() .selectors( selectMethod(testClass, "test") ).build(); @@ -159,7 +159,7 @@ void uniqueIdsAreStoredInDiscoveryRequest() { var id2 = UniqueId.forEngine("engine").append("foo", "id2"); // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .selectors( selectUniqueId(id1), selectUniqueId(id2) @@ -183,7 +183,7 @@ void engineFiltersAreStoredInDiscoveryRequest() { TestEngine engine3 = new TestEngineStub("engine3"); // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .filters(includeEngines(engine1.getId(), engine2.getId())) .build(); // @formatter:on @@ -201,7 +201,7 @@ void discoveryFiltersAreStoredInDiscoveryRequest() { var filter1 = new DiscoveryFilterStub<>("filter1"); var filter2 = new DiscoveryFilterStub<>("filter2"); // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .filters(filter1, filter2) .build(); // @formatter:on @@ -215,7 +215,7 @@ void postDiscoveryFiltersAreStoredInDiscoveryRequest() { var postFilter1 = new PostDiscoveryFilterStub("postFilter1"); var postFilter2 = new PostDiscoveryFilterStub("postFilter2"); // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .filters(postFilter1, postFilter2) .build(); // @formatter:on @@ -227,7 +227,7 @@ void postDiscoveryFiltersAreStoredInDiscoveryRequest() { @Test void exceptionForIllegalFilterClass() { Exception exception = assertThrows(PreconditionViolationException.class, - () -> request().filters(o -> excluded("reason"))); + () -> discoveryRequest().filters(o -> excluded("reason"))); assertThat(exception).hasMessageStartingWith("Filter"); assertThat(exception).hasMessageEndingWith( @@ -240,7 +240,7 @@ class DiscoveryConfigurationParameterTests { @Test void withoutConfigurationParametersSet_NoConfigurationParametersAreStoredInDiscoveryRequest() { - var discoveryRequest = request().build(); + var discoveryRequest = discoveryRequest().build(); var configParams = discoveryRequest.getConfigurationParameters(); assertThat(configParams.get("key")).isNotPresent(); @@ -249,7 +249,7 @@ void withoutConfigurationParametersSet_NoConfigurationParametersAreStoredInDisco @Test void configurationParameterAddedDirectly_isStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParameter("key", "value") .build(); // @formatter:on @@ -261,7 +261,7 @@ void configurationParameterAddedDirectly_isStoredInDiscoveryRequest() { @Test void configurationParameterAddedDirectlyTwice_overridesPreviousValueInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParameter("key", "value") .configurationParameter("key", "value-new") .build(); @@ -274,7 +274,7 @@ void configurationParameterAddedDirectlyTwice_overridesPreviousValueInDiscoveryR @Test void multipleConfigurationParametersAddedDirectly_areStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParameter("key1", "value1") .configurationParameter("key2", "value2") .build(); @@ -288,7 +288,7 @@ void multipleConfigurationParametersAddedDirectly_areStoredInDiscoveryRequest() @Test void configurationParameterAddedByMap_isStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParameters(Map.of("key", "value")) .build(); // @formatter:on @@ -304,7 +304,7 @@ void multipleConfigurationParametersAddedByMap_areStoredInDiscoveryRequest() { configurationParams.put("key2", "value2"); // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParameters(configurationParams) .build(); // @formatter:on @@ -317,7 +317,7 @@ void multipleConfigurationParametersAddedByMap_areStoredInDiscoveryRequest() { @Test void configurationParametersResource_areStoredInDiscoveryRequest() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParametersResources("config-test.properties") .build(); // @formatter:on @@ -331,7 +331,7 @@ void configurationParametersResource_areStoredInDiscoveryRequest() { @Test void configurationParametersResource_explicitConfigParametersOverrideResource() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParametersResources("config-test.properties") .configurationParameter("com.example.prop.first", "first value override") .build(); @@ -345,7 +345,7 @@ void configurationParametersResource_explicitConfigParametersOverrideResource() @Test void configurationParametersResource_lastDeclaredResourceFileWins() { // @formatter:off - var discoveryRequest = request() + var discoveryRequest = discoveryRequest() .configurationParametersResources("config-test.properties") .configurationParametersResources("config-test-override.properties") .build(); @@ -362,14 +362,14 @@ class DiscoveryListenerTests { @Test void usesAbortOnFailureByDefault() { - var request = request().build(); + var request = discoveryRequest().build(); assertThat(request.getDiscoveryListener()).isEqualTo(abortOnFailure()); } @Test void onlyAddsAbortOnFailureOnce() { - var request = request() // + var request = discoveryRequest() // .listeners(abortOnFailure()) // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "abortOnFailure") // .build(); @@ -379,7 +379,7 @@ void onlyAddsAbortOnFailureOnce() { @Test void onlyAddsLoggingOnce() { - var request = request() // + var request = discoveryRequest() // .listeners(logging()) // .configurationParameter(DEFAULT_DISCOVERY_LISTENER_CONFIGURATION_PROPERTY_NAME, "logging") // .build(); @@ -389,7 +389,7 @@ void onlyAddsLoggingOnce() { @Test void createsCompositeForMultipleListeners() { - var request = request() // + var request = discoveryRequest() // .listeners(logging(), abortOnFailure()) // .build(); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java index c66f1d3f487d..31dc144744c6 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java @@ -11,6 +11,8 @@ package org.junit.platform.launcher.core; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.discoveryRequest; +import static org.junit.platform.launcher.core.LauncherExecutionRequestBuilder.executionRequest; import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncherConfigBuilderWithDisabledServiceLoading; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; @@ -32,14 +34,14 @@ class LauncherSessionTests { .addLauncherSessionListeners(firstSessionListener, secondSessionListener) // .addTestEngines(new TestEngineStub()) // .build(); - LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request().build(); + LauncherDiscoveryRequest discoveryRequest = discoveryRequest().build(); @SuppressWarnings("deprecation") @Test void callsRegisteredListenersWhenLauncherIsUsedDirectly() { var launcher = LauncherFactory.create(launcherConfig); - var testPlan = launcher.discover(request); + var testPlan = launcher.discover(discoveryRequest); var inOrder = inOrder(firstSessionListener, secondSessionListener); var launcherSession = ArgumentCaptor.forClass(LauncherSession.class); @@ -55,28 +57,28 @@ void callsRegisteredListenersWhenLauncherIsUsedDirectly() { inOrder.verify(secondSessionListener).launcherSessionClosed(launcherSession.getValue()); inOrder.verify(firstSessionListener).launcherSessionClosed(launcherSession.getValue()); - launcher.execute(request); + launcher.execute(discoveryRequest); inOrder.verify(firstSessionListener).launcherSessionOpened(launcherSession.capture()); inOrder.verify(secondSessionListener).launcherSessionOpened(launcherSession.getValue()); inOrder.verify(secondSessionListener).launcherSessionClosed(launcherSession.getValue()); inOrder.verify(firstSessionListener).launcherSessionClosed(launcherSession.getValue()); - testPlan = launcher.discover(request); + testPlan = launcher.discover(discoveryRequest); inOrder.verify(firstSessionListener).launcherSessionOpened(launcherSession.capture()); inOrder.verify(secondSessionListener).launcherSessionOpened(launcherSession.getValue()); inOrder.verify(secondSessionListener).launcherSessionClosed(launcherSession.getValue()); inOrder.verify(firstSessionListener).launcherSessionClosed(launcherSession.getValue()); - launcher.execute(LauncherExecutionRequestBuilder.request(testPlan).build()); + launcher.execute(executionRequest(testPlan).build()); inOrder.verify(firstSessionListener).launcherSessionOpened(launcherSession.capture()); inOrder.verify(secondSessionListener).launcherSessionOpened(launcherSession.getValue()); inOrder.verify(secondSessionListener).launcherSessionClosed(launcherSession.getValue()); inOrder.verify(firstSessionListener).launcherSessionClosed(launcherSession.getValue()); - launcher.execute(LauncherExecutionRequestBuilder.request(request).build()); + launcher.execute(executionRequest(discoveryRequest).build()); inOrder.verify(firstSessionListener).launcherSessionOpened(launcherSession.capture()); inOrder.verify(secondSessionListener).launcherSessionOpened(launcherSession.getValue()); @@ -95,13 +97,13 @@ void callsRegisteredListenersWhenLauncherIsUsedViaSession() { inOrder.verify(secondSessionListener).launcherSessionOpened(session); verifyNoMoreInteractions(firstSessionListener, secondSessionListener); - var testPlan = launcher.discover(request); + var testPlan = launcher.discover(discoveryRequest); launcher.execute(testPlan); - launcher.execute(request); + launcher.execute(discoveryRequest); - testPlan = launcher.discover(request); - launcher.execute(LauncherExecutionRequestBuilder.request(testPlan).build()); - launcher.execute(LauncherExecutionRequestBuilder.request(request).build()); + testPlan = launcher.discover(discoveryRequest); + launcher.execute(executionRequest(testPlan).build()); + launcher.execute(executionRequest(discoveryRequest).build()); verifyNoMoreInteractions(firstSessionListener, secondSessionListener); @@ -117,17 +119,16 @@ void callsRegisteredListenersWhenLauncherIsUsedViaSession() { void closedSessionCannotBeUsed() { var session = LauncherFactory.openSession(launcherConfig); var launcher = session.getLauncher(); - var testPlan = launcher.discover(request); + var testPlan = launcher.discover(discoveryRequest); session.close(); - assertThrows(PreconditionViolationException.class, () -> launcher.discover(request)); + assertThrows(PreconditionViolationException.class, () -> launcher.discover(discoveryRequest)); assertThrows(PreconditionViolationException.class, () -> launcher.execute(testPlan)); - assertThrows(PreconditionViolationException.class, () -> launcher.execute(request)); + assertThrows(PreconditionViolationException.class, () -> launcher.execute(discoveryRequest)); + assertThrows(PreconditionViolationException.class, () -> launcher.execute(executionRequest(testPlan).build())); assertThrows(PreconditionViolationException.class, - () -> launcher.execute(LauncherExecutionRequestBuilder.request(testPlan).build())); - assertThrows(PreconditionViolationException.class, - () -> launcher.execute(LauncherExecutionRequestBuilder.request(request).build())); + () -> launcher.execute(executionRequest(discoveryRequest).build())); } } From af47043e61540213c23215d34b548ac996994f00 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:39:53 +0200 Subject: [PATCH 27/33] Improve wording --- .../asciidoc/release-notes/release-notes-6.0.0-RC2.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc index 07c238233e27..4206b52977cf 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -42,12 +42,12 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. * New `executionRequest(...)` methods in `{LauncherExecutionRequestBuilder}`, which are aliases for the existing `request(...)` methods and are intended to be used via a `static` import. -* New `selectClasses(...)` and `selectClassesByName(...)` utility methods have been +* New `selectClasses(...)` and `selectClassesByName(...)` factory methods have been introduced in `{DiscoverySelectors}` to simplify use cases where one needs to select multiple individual test classes for the `Launcher` or `EngineTestKit`. * New `selectors(List)` builder method for `{EngineTestKit}` which can be used in - conjunction with the new `selectClasses(...)` and `selectClassesByName(...)` methods in - `DiscoverySelectors`. + conjunction with the new `selectClasses(...)` and `selectClassesByName(...)` factory + methods in `DiscoverySelectors`. [[release-notes-6.0.0-RC2-junit-jupiter]] From 9550e4180771c67adb28cbbb6d533f94e310226f Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:55:24 +0200 Subject: [PATCH 28/33] Fix Javadoc for execute(LauncherExecutionRequest) plus polishing --- .../org/junit/platform/launcher/Launcher.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java index 50847f5e15c7..988751c51ba6 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java @@ -81,12 +81,11 @@ public interface Launcher { * {@link #execute(TestPlan, TestExecutionListener...)} for execution at * most once. * - * @param launcherDiscoveryRequest the launcher discovery request; never - * {@code null} + * @param discoveryRequest the launcher discovery request; never {@code null} * @return an unmodifiable {@code TestPlan} that contains all resolved * {@linkplain TestIdentifier identifiers} from all registered engines */ - TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest); + TestPlan discover(LauncherDiscoveryRequest discoveryRequest); /** * Execute a {@link TestPlan} which is built according to the supplied @@ -106,14 +105,14 @@ public interface Launcher { * performance degradation (e.g., classpath scanning) of running test * discovery twice. * - * @param launcherDiscoveryRequest the launcher discovery request; never {@code null} + * @param discoveryRequest the launcher discovery request; never {@code null} * @param listeners additional test execution listeners; never {@code null} * @deprecated Please use {@link #execute(LauncherExecutionRequest)} instead. */ @Deprecated(since = "6.0") @API(status = DEPRECATED, since = "6.0") - default void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { - var executionRequest = LauncherExecutionRequestBuilder.request(launcherDiscoveryRequest) // + default void execute(LauncherDiscoveryRequest discoveryRequest, TestExecutionListener... listeners) { + var executionRequest = LauncherExecutionRequestBuilder.request(discoveryRequest) // .listeners(listeners) // .build(); execute(executionRequest); @@ -146,8 +145,8 @@ default void execute(TestPlan testPlan, TestExecutionListener... listeners) { } /** - * Execute tests according to the supplied {@link LauncherExecutionRequest} - * {@linkplain #registerTestExecutionListeners registered listeners} about + * Execute tests according to the supplied {@link LauncherExecutionRequest} and + * notify {@linkplain #registerTestExecutionListeners registered listeners} about * the progress and results of the execution. * *

Test execution listeners supplied @@ -167,11 +166,10 @@ default void execute(TestPlan testPlan, TestExecutionListener... listeners) { * supplied execution request to avoid the potential performance degradation * (e.g., classpath scanning) of running test discovery twice. * - * @param launcherExecutionRequest the launcher execution request; never - * {@code null} + * @param executionRequest the launcher execution request; never {@code null} * @since 6.0 */ @API(status = MAINTAINED, since = "6.0") - void execute(LauncherExecutionRequest launcherExecutionRequest); + void execute(LauncherExecutionRequest executionRequest); } From b6c97c7c5f0cd9a2a09115e63cad9dffe5db3e73 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:56:40 +0200 Subject: [PATCH 29/33] Undeprecate traditional execute() methods in the Launcher API This commit undeprecates the execute(TestPlan, ...) and execute(LauncherDiscoveryRequest, ...) methods in the Launcher API. See #4724 Closes #4866 --- .../release-notes/release-notes-6.0.0-RC2.adoc | 3 +++ .../java/org/junit/platform/launcher/Launcher.java | 14 +++++++------- .../launcher/core/LauncherSessionTests.java | 5 ++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc index 4206b52977cf..2333d5672a90 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -36,6 +36,9 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. [[release-notes-6.0.0-RC2-junit-platform-new-features-and-improvements]] ==== New Features and Improvements +* The `execute(TestPlan,{nbsp}TestExecutionListener...)` and + `execute(LauncherDiscoveryRequest,{nbsp}TestExecutionListener...)` methods in the + `Launcher` API are no longer deprecated. * New `discoveryRequest()` method in `{LauncherDiscoveryRequestBuilder}`, which is an alias for the existing `request()` method and is intended to be used via a `static` import. diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java index 988751c51ba6..99415b639b05 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/Launcher.java @@ -10,7 +10,6 @@ package org.junit.platform.launcher; -import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; @@ -107,10 +106,9 @@ public interface Launcher { * * @param discoveryRequest the launcher discovery request; never {@code null} * @param listeners additional test execution listeners; never {@code null} - * @deprecated Please use {@link #execute(LauncherExecutionRequest)} instead. + * @see #execute(TestPlan, TestExecutionListener...) + * @see #execute(LauncherExecutionRequest) */ - @Deprecated(since = "6.0") - @API(status = DEPRECATED, since = "6.0") default void execute(LauncherDiscoveryRequest discoveryRequest, TestExecutionListener... listeners) { var executionRequest = LauncherExecutionRequestBuilder.request(discoveryRequest) // .listeners(listeners) // @@ -133,10 +131,10 @@ default void execute(LauncherDiscoveryRequest discoveryRequest, TestExecutionLis * @param testPlan the test plan to execute; never {@code null} * @param listeners additional test execution listeners; never {@code null} * @since 1.4 - * @deprecated Please use {@link #execute(LauncherExecutionRequest)} instead. + * @see #execute(LauncherDiscoveryRequest, TestExecutionListener...) + * @see #execute(LauncherExecutionRequest) */ - @Deprecated(since = "6.0") - @API(status = DEPRECATED, since = "6.0") + @API(status = STABLE, since = "1.4") default void execute(TestPlan testPlan, TestExecutionListener... listeners) { var executionRequest = LauncherExecutionRequestBuilder.request(testPlan) // .listeners(listeners) // @@ -168,6 +166,8 @@ default void execute(TestPlan testPlan, TestExecutionListener... listeners) { * * @param executionRequest the launcher execution request; never {@code null} * @since 6.0 + * @see #execute(LauncherDiscoveryRequest, TestExecutionListener...) + * @see #execute(TestPlan, TestExecutionListener...) */ @API(status = MAINTAINED, since = "6.0") void execute(LauncherExecutionRequest executionRequest); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java index 31dc144744c6..0cef6ce6f90c 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherSessionTests.java @@ -36,7 +36,6 @@ class LauncherSessionTests { .build(); LauncherDiscoveryRequest discoveryRequest = discoveryRequest().build(); - @SuppressWarnings("deprecation") @Test void callsRegisteredListenersWhenLauncherIsUsedDirectly() { var launcher = LauncherFactory.create(launcherConfig); @@ -87,7 +86,7 @@ void callsRegisteredListenersWhenLauncherIsUsedDirectly() { } @Test - @SuppressWarnings({ "deprecation", "resource" }) + @SuppressWarnings("resource") void callsRegisteredListenersWhenLauncherIsUsedViaSession() { var session = LauncherFactory.openSession(launcherConfig); var launcher = session.getLauncher(); @@ -115,7 +114,7 @@ void callsRegisteredListenersWhenLauncherIsUsedViaSession() { } @Test - @SuppressWarnings({ "deprecation", "resource" }) + @SuppressWarnings("resource") void closedSessionCannotBeUsed() { var session = LauncherFactory.openSession(launcherConfig); var launcher = session.getLauncher(); From 43899a46640afd275dbb40b4671ee915e402f009 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 25 Aug 2025 15:59:59 +0200 Subject: [PATCH 30/33] Prepare update to Groovy 5.0 --- .github/renovate.json5 | 7 ------- gradle/libs.versions.toml | 2 +- jupiter-tests/jupiter-tests.gradle.kts | 2 +- platform-tests/platform-tests.gradle.kts | 4 ++-- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index ea024d3d17e6..3f208aaff40a 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -11,13 +11,6 @@ 'org.codehaus.groovy:{/,}**', ], }, - { - matchCurrentValue: '/^4\\./', - allowedVersions: '(,5.0)', - matchPackageNames: [ - 'org.apache.groovy:{/,}**', - ], - }, { matchCurrentValue: '/^1\\./', allowedVersions: '/^1\\..*-groovy-2\\.*/', diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cb6503c5da88..c24292745b77 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ commons-io = { module = "commons-io:commons-io", version = "2.20.0" } errorProne-core = { module = "com.google.errorprone:error_prone_core", version = "2.41.0" } fastcsv = { module = "de.siegmar:fastcsv", version = "4.0.0" } -groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.28" } +groovy = { module = "org.apache.groovy:groovy", version = "4.0.28" } groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.23" } hamcrest = { module = "org.hamcrest:hamcrest", version = "3.0" } jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" } diff --git a/jupiter-tests/jupiter-tests.gradle.kts b/jupiter-tests/jupiter-tests.gradle.kts index 9b1baaf781a7..ad4f82ba20ad 100644 --- a/jupiter-tests/jupiter-tests.gradle.kts +++ b/jupiter-tests/jupiter-tests.gradle.kts @@ -22,7 +22,7 @@ dependencies { testImplementation(libs.jimfs) testImplementation(libs.junit4) testImplementation(libs.kotlinx.coroutines) - testImplementation(libs.groovy4) + testImplementation(libs.groovy) testImplementation(libs.memoryfilesystem) testImplementation(testFixtures(projects.junitJupiterApi)) testImplementation(testFixtures(projects.junitJupiterEngine)) diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index ae6e94d3cc5f..bf1d21c7816f 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -69,7 +69,7 @@ dependencies { // Add all projects to the classpath for tests using classpath scanning testRuntimeOnly(it) } - testRuntimeOnly(libs.groovy4) { + testRuntimeOnly(libs.groovy) { because("`ReflectionUtilsTests.findNestedClassesWithInvalidNestedClassFile` needs it") } woodstox(libs.woodstox) @@ -79,7 +79,7 @@ dependencies { jmh(libs.junit4) // --- ProcessStarter dependencies -------------------------------------------- - processStarter.implementationConfigurationName(libs.groovy4) { + processStarter.implementationConfigurationName(libs.groovy) { because("it provides convenience methods to handle process output") } processStarter.implementationConfigurationName(libs.commons.io) { From a155d6eec6dbc31d1b36adb6e4737cfa7133b473 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:00:59 +0000 Subject: [PATCH 31/33] Update dependency org.apache.groovy:groovy to v5 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c24292745b77..6ef31e3779d9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ commons-io = { module = "commons-io:commons-io", version = "2.20.0" } errorProne-core = { module = "com.google.errorprone:error_prone_core", version = "2.41.0" } fastcsv = { module = "de.siegmar:fastcsv", version = "4.0.0" } -groovy = { module = "org.apache.groovy:groovy", version = "4.0.28" } +groovy = { module = "org.apache.groovy:groovy", version = "5.0.0" } groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.23" } hamcrest = { module = "org.hamcrest:hamcrest", version = "3.0" } jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" } From 66bd8f2197805825f4ba9d1b41610b6640a22867 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 25 Aug 2025 17:16:24 +0200 Subject: [PATCH 32/33] Finalize 6.0.0-RC2 release notes --- .../release-notes-6.0.0-RC2.adoc | 37 ++----------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc index 2333d5672a90..cc270b4af04e 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC2.adoc @@ -1,7 +1,7 @@ [[release-notes-6.0.0-RC2]] == 6.0.0-RC2 -*Date of Release:* ❓ +*Date of Release:* August 25, 2025 *Scope:* Minor enhancements and bug fixes since 6.0.0-RC1. @@ -28,11 +28,6 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. `TestEngine` registration order after pruning test engines without tests, thereby ensuring reliable test execution order of multiple test engines. -[[release-notes-6.0.0-RC2-junit-platform-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - [[release-notes-6.0.0-RC2-junit-platform-new-features-and-improvements]] ==== New Features and Improvements @@ -56,36 +51,10 @@ guidance on upgrading from JUnit 5.x.y to 6.0.0. [[release-notes-6.0.0-RC2-junit-jupiter]] === JUnit Jupiter -[[release-notes-6.0.0-RC2-junit-jupiter-bug-fixes]] -==== Bug Fixes - -* ❓ - -[[release-notes-6.0.0-RC2-junit-jupiter-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - -[[release-notes-6.0.0-RC2-junit-jupiter-new-features-and-improvements]] -==== New Features and Improvements - -* ❓ +No changes. [[release-notes-6.0.0-RC2-junit-vintage]] === JUnit Vintage -[[release-notes-6.0.0-RC2-junit-vintage-bug-fixes]] -==== Bug Fixes - -* ❓ - -[[release-notes-6.0.0-RC2-junit-vintage-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - -[[release-notes-6.0.0-RC2-junit-vintage-new-features-and-improvements]] -==== New Features and Improvements - -* ❓ +No changes. From 281f4e9d52e113f445a29f625ce48084e57493a1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 25 Aug 2025 17:20:08 +0200 Subject: [PATCH 33/33] Release 6.0.0-RC2 --- README.md | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d9332f740aff..038992256fb2 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This repository is the home of JUnit Platform, Jupiter, and Vintage. ## Latest Releases - General Availability (GA): [JUnit 5.13.4](https://github.com/junit-team/junit-framework/releases/tag/r5.13.4) (July 21, 2025) -- Preview (Milestone/Release Candidate): [JUnit 6.0.0-RC1](https://github.com/junit-team/junit-framework/releases/tag/r6.0.0-RC1) (August 20, 2025) +- Preview (Milestone/Release Candidate): [JUnit 6.0.0-RC2](https://github.com/junit-team/junit-framework/releases/tag/r6.0.0-RC2) (August 25, 2025) ## Documentation diff --git a/gradle.properties b/gradle.properties index 000b32c34896..a2adbcd6c5d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version = 6.0.0-SNAPSHOT +version = 6.0.0-RC2 # We need more metaspace due to apparent memory leak in Asciidoctor/JRuby org.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError