From fa8c725a3d62439a80f1ad3ad99028e416e65492 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 21 Feb 2025 14:28:25 +0100 Subject: [PATCH 01/13] Back to snapshots for further development --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 23f0682e81cf..85e568f178ea 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,13 @@ group = org.junit -version = 5.12.0 +version = 5.12.1-SNAPSHOT jupiterGroup = org.junit.jupiter platformGroup = org.junit.platform -platformVersion = 1.12.0 +platformVersion = 1.12.1-SNAPSHOT vintageGroup = org.junit.vintage -vintageVersion = 5.12.0 +vintageVersion = 5.12.1-SNAPSHOT # We need more metaspace due to apparent memory leak in Asciidoctor/JRuby # The exports are needed due to https://github.com/diffplug/spotless/issues/834 From f18554ef2cc85b42c50e6bb44a5ed54ea648fbeb Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 4 Mar 2025 11:47:55 +0100 Subject: [PATCH 02/13] Overhaul Gradle section regarding dependency alignment (#4358) Resolves #4343. --------- Co-authored-by: Sam Brannen <104798+sbrannen@users.noreply.github.com> (cherry picked from commit 0068c244f4607b35c4b330204f8632fe03ee9a25) --- .../asciidoc/user-guide/running-tests.adoc | 130 +++++++++++++----- 1 file changed, 95 insertions(+), 35 deletions(-) diff --git a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc index dfd49d779a28..db03995cb078 100644 --- a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc @@ -13,11 +13,6 @@ however, that it is recommended to use IDEA 2017.3 or newer since more recent ve IDEA download the following JARs automatically based on the API version used in the project: `junit-platform-launcher`, `junit-jupiter-engine`, and `junit-vintage-engine`. -WARNING: IntelliJ IDEA releases prior to IDEA 2017.3 bundle specific versions of JUnit 5. -Thus, if you want to use a newer version of JUnit Jupiter, execution of tests within the -IDE might fail due to version conflicts. In such cases, please follow the instructions -below to use a newer version of JUnit 5 than the one bundled with IntelliJ IDEA. - In order to use a different JUnit 5 version (e.g., {jupiter-version}), you may need to include the corresponding versions of the `junit-platform-launcher`, `junit-jupiter-engine`, and `junit-vintage-engine` JARs in the classpath. @@ -27,9 +22,7 @@ include the corresponding versions of the `junit-platform-launcher`, [subs=attributes+] ---- testImplementation(platform("org.junit:junit-bom:{bom-version}")) -testRuntimeOnly("org.junit.platform:junit-platform-launcher") { - because("Only needed to run tests in a version of IntelliJ IDEA that bundles older versions") -} +testRuntimeOnly("org.junit.platform:junit-platform-launcher") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") testRuntimeOnly("org.junit.vintage:junit-vintage-engine") ---- @@ -40,7 +33,6 @@ testRuntimeOnly("org.junit.vintage:junit-vintage-engine") ---- - org.junit.platform junit-platform-launcher @@ -150,48 +142,63 @@ test { ---- Please refer to the -https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_test[official Gradle documentation] +https://docs.gradle.org/current/userguide/java_testing.html[official Gradle documentation] for a comprehensive list of options. [[running-tests-build-gradle-bom]] ===== Aligning dependency versions +TIP: See <> for details on how to override the version +of JUnit used in your Spring Boot application. + Unless you're using Spring Boot which defines its own way of managing dependencies, it is -recommended to use the JUnit Platform BOM to align the versions of all JUnit 5 artifacts. +recommended to use the JUnit Platform <> to align the +versions of all JUnit 5 artifacts. [source,groovy,indent=0] [subs=attributes+] +.Explicit platform dependency on the BOM ---- dependencies { testImplementation(platform("org.junit:junit-bom:{bom-version}")) + testImplementation("org.junit.jupiter:junit-jupiter") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") } ---- Using the BOM allows you to omit the version when declaring dependencies on all artifacts with the `org.junit.platform`, `org.junit.jupiter`, and `org.junit.vintage` group IDs. -TIP: See <> for details on how to override the version -of JUnit used in your Spring Boot application. - -[[running-tests-build-gradle-config-params]] -===== Configuration Parameters - -The standard Gradle `test` task currently does not provide a dedicated DSL to set JUnit -Platform <> to influence test -discovery and execution. However, you can provide configuration parameters within the -build script via system properties (as shown below) or via the -`junit-platform.properties` file. +Since all JUnit artifacts declare a +https://docs.gradle.org/current/userguide/platforms.html[platform] dependency on the BOM, +you usually don't need to declare an explicit dependency on it yourself. Instead, it's +sufficient to declare _one_ regular dependency that includes a version number. Gradle will +then pull in the BOM automatically so you can omit the version for all other JUnit 5 +artifacts. [source,groovy,indent=0] +[subs=attributes+] +.Implicit platform dependency on the BOM ---- -test { - // ... - systemProperty("junit.jupiter.conditions.deactivate", "*") - systemProperty("junit.jupiter.extensions.autodetection.enabled", true) - systemProperty("junit.jupiter.testinstance.lifecycle.default", "per_class") - // ... +dependencies { + testImplementation("org.junit.jupiter:junit-jupiter:{jupiter-version}") // <1> + testRuntimeOnly("org.junit.platform:junit-platform-launcher") // <2> } ---- +<1> Dependency declaration with explicit version. Pulls in the `junit-bom` automatically. +<2> Dependency declaration without version. The version is supplied by the `junit-bom`. + +[WARNING] +.Declaring a dependency on junit-platform-launcher +==== +Even though pre-8.0 versions of Gradle don't require declaring an explicit +dependency on `junit-platform-launcher`, it is recommended to do so to ensure the versions +of JUnit artifacts on the test runtime classpath are aligned. + +Moreover, doing so is recommended and in some cases even required when importing the +project into an IDE like <> or +<>. +==== [[running-tests-build-gradle-engines-configure]] ===== Configuring Test Engines @@ -205,7 +212,38 @@ on the dependency-aggregating JUnit Jupiter artifact similar to the following. [subs=attributes+] ---- dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:{jupiter-version}") // version can be omitted when using the BOM + testImplementation("org.junit.jupiter:junit-jupiter:{jupiter-version}") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") +} +---- + +Alternatively, you can use Gradle's +https://docs.gradle.org/current/userguide/jvm_test_suite_plugin.html[JVM Test Suite] +support. + +[source,kotlin,indent=0] +[subs=attributes+] +.Kotlin DSL +---- +testing { + suites { + named("test") { + useJUnitJupiter("{jupiter-version}") + } + } +} +---- + +[source,groovy,indent=0] +[subs=attributes+] +.Groovy DSL +---- +testing { + suites { + test { + useJUnitJupiter("{jupiter-version}") + } + } } ---- @@ -218,7 +256,28 @@ implementation similar to the following. ---- dependencies { testImplementation("junit:junit:{junit4-version}") - testRuntimeOnly("org.junit.vintage:junit-vintage-engine:{vintage-version}") // version can be omitted when using the BOM + testRuntimeOnly("org.junit.vintage:junit-vintage-engine:{vintage-version}") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") +} +---- + +[[running-tests-build-gradle-config-params]] +===== Configuration Parameters + +The standard Gradle `test` task currently does not provide a dedicated DSL to set JUnit +Platform <> to influence test +discovery and execution. However, you can provide configuration parameters within the +build script via system properties (as shown below) or via the +`junit-platform.properties` file. + +[source,groovy,indent=0] +---- +test { + // ... + systemProperty("junit.jupiter.conditions.deactivate", "*") + systemProperty("junit.jupiter.extensions.autodetection.enabled", true) + systemProperty("junit.jupiter.testinstance.lifecycle.default", "per_class") + // ... } ---- @@ -248,8 +307,8 @@ test { Other logging frameworks provide different means to redirect messages logged using `java.util.logging`. For example, for {Logback} you can use the -https://www.slf4j.org/legacy.html#jul-to-slf4j[JUL to SLF4J Bridge] by adding an -additional dependency to the runtime classpath. +https://www.slf4j.org/legacy.html#jul-to-slf4j[JUL to SLF4J Bridge] by adding it as a +dependency to the test runtime classpath. [[running-tests-build-maven]] ==== Maven @@ -288,7 +347,8 @@ Maven build as follows. ===== Aligning dependency versions Unless you're using Spring Boot which defines its own way of managing dependencies, it is -recommended to use the JUnit Platform BOM to align the versions of all JUnit 5 artifacts. +recommended to use the JUnit Platform <> to align the +versions of all JUnit 5 artifacts. [source,xml,indent=0] [subs=attributes+] @@ -580,8 +640,8 @@ managing the version of JUnit used in your project. In addition, the Jupiter, AssertJ, Mockito, etc. If your build relies on dependency management support from Spring Boot, you should not -import the <> in your build script since that -will result in duplicate (and potentially conflicting) management of JUnit dependencies. +import JUnit's <> in your build script since that would +result in duplicate (and potentially conflicting) management of JUnit dependencies. If you need to override the version of a dependency used in your Spring Boot application, you have to override the exact name of the From 7030418723ad0f53a9ce4a09aac5fc30c914ed19 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 8 Mar 2025 12:14:49 +0100 Subject: [PATCH 03/13] Exclude shadowed packages from API reports (cherry picked from commit 1caca7dbb0fc9bf37622e160bd72cd8d4e00ab1a) --- .../src/tools/java/org/junit/api/tools/ApiReportGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java b/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java index 02b7baa3f47d..100593ceb93d 100644 --- a/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java +++ b/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java @@ -133,6 +133,7 @@ ApiReport generateReport(String... packages) { private static ScanResult scanClasspath(String[] packages) { var classGraph = new ClassGraph() // .acceptPackages(packages) // + .rejectPackages("*.shadow.*") // .disableNestedJarScanning() // .enableClassInfo() // .enableMethodInfo() // From 31d60b7751e415853b582a275fe626b0358ab939 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sun, 9 Mar 2025 13:28:16 +0100 Subject: [PATCH 04/13] Split API reports by module and package --- documentation/documentation.gradle.kts | 1 + .../api/tools/AbstractApiReportWriter.java | 29 ++++-- .../junit/api/tools/ApiReportGenerator.java | 97 ++++++++++--------- .../api/tools/AsciidocApiReportWriter.java | 18 +++- .../java/org/junit/api/tools/Declaration.java | 30 +++++- .../junit/api/tools/HtmlApiReportWriter.java | 17 +++- .../api/tools/MarkdownApiReportWriter.java | 17 +++- 7 files changed, 142 insertions(+), 67 deletions(-) diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 45095cdef845..77f40b0cca43 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -55,6 +55,7 @@ dependencies { // Pull in all "modular projects" to ensure that they are included // in reports generated by the ApiReportGenerator. modularProjects.forEach { apiReport(it) } + apiReport(libs.openTestReporting.tooling.spi) // Pull in all "mavenized projects" to ensure that they are included // in the generation of build provenance attestation. diff --git a/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java b/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java index 4e08a529fbe1..a35b60211bb4 100644 --- a/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java +++ b/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java @@ -11,10 +11,13 @@ package org.junit.api.tools; import static java.lang.String.format; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toList; import java.io.PrintWriter; import java.util.List; import java.util.Set; +import java.util.TreeMap; import org.apiguardian.api.API.Status; @@ -49,12 +52,22 @@ public void printDeclarationInfo(PrintWriter out, Set statuses) { protected void printDeclarationSection(Set statuses, Status status, List declarations, PrintWriter out) { printDeclarationSectionHeader(statuses, status, declarations, out); - if (!declarations.isEmpty()) { - printDeclarationTableHeader(out); - declarations.forEach(it -> printDeclarationTableRow(it, out)); - printDeclarationTableFooter(out); - out.println(); - } + declarations.stream() // + .collect(groupingBy(Declaration::moduleName, TreeMap::new, toList())) // + .forEach((moduleName, moduleDeclarations) -> { + out.println(h4("Module " + moduleName)); + out.println(); + moduleDeclarations.stream() // + .collect(groupingBy(Declaration::packageName, TreeMap::new, toList())) // + .forEach((packageName, packageDeclarations) -> { + out.println(h5("Package " + packageName)); + out.println(); + printDeclarationTableHeader(out); + packageDeclarations.forEach(it -> printDeclarationTableRow(it, out)); + printDeclarationTableFooter(out); + out.println(); + }); + }); } protected void printDeclarationSectionHeader(Set statuses, Status status, List declarations, @@ -74,6 +87,10 @@ protected void printDeclarationSectionHeader(Set statuses, Status status protected abstract String h2(String header); + protected abstract String h4(String header); + + protected abstract String h5(String header); + protected abstract String code(String element); protected abstract String italic(String element); diff --git a/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java b/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java index 100593ceb93d..d256652de1b2 100644 --- a/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java +++ b/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java @@ -10,13 +10,16 @@ package org.junit.api.tools; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.toCollection; import java.io.BufferedOutputStream; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.io.UncheckedIOException; +import java.lang.module.ModuleFinder; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -25,6 +28,7 @@ import java.util.EnumSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.stream.Stream; @@ -52,30 +56,30 @@ public static void main(String... args) { // CAUTION: The output produced by this method is used to // generate a table in the User Guide. - var reportGenerator = new ApiReportGenerator(); + try (var scanResult = scanClasspath()) { - // scan all types below "org.junit" package - var apiReport = reportGenerator.generateReport("org.junit"); - - // ApiReportWriter reportWriter = new MarkdownApiReportWriter(apiReport); - ApiReportWriter reportWriter = new AsciidocApiReportWriter(apiReport); - // ApiReportWriter reportWriter = new HtmlApiReportWriter(apiReport); - - // reportWriter.printReportHeader(new PrintWriter(System.out, true)); - - // Print report for all Usage enum constants - // reportWriter.printDeclarationInfo(new PrintWriter(System.out, true), EnumSet.allOf(Status.class)); - - // Print report only for specific Status constants, defaults to only EXPERIMENTAL - parseArgs(args).forEach((status, opener) -> { - try (var stream = opener.openStream()) { - var writer = new PrintWriter(stream == null ? System.out : stream, true); - reportWriter.printDeclarationInfo(writer, EnumSet.of(status)); - } - catch (IOException e) { - throw new UncheckedIOException("Failed to write report", e); - } - }); + var apiReport = generateReport(scanResult); + + // ApiReportWriter reportWriter = new MarkdownApiReportWriter(apiReport); + ApiReportWriter reportWriter = new AsciidocApiReportWriter(apiReport); + // ApiReportWriter reportWriter = new HtmlApiReportWriter(apiReport); + + // reportWriter.printReportHeader(new PrintWriter(System.out, true)); + + // Print report for all Usage enum constants + // reportWriter.printDeclarationInfo(new PrintWriter(System.out, true), EnumSet.allOf(Status.class)); + + // Print report only for specific Status constants, defaults to only EXPERIMENTAL + parseArgs(args).forEach((status, opener) -> { + try (var stream = opener.openStream()) { + var writer = new PrintWriter(stream == null ? System.out : stream, true, UTF_8); + reportWriter.printDeclarationInfo(writer, EnumSet.of(status)); + } + catch (IOException e) { + throw new UncheckedIOException("Failed to write report", e); + } + }); + } } // ------------------------------------------------------------------------- @@ -102,45 +106,48 @@ private interface StreamOpener { OutputStream openStream() throws IOException; } - ApiReport generateReport(String... packages) { + private static ApiReport generateReport(ScanResult scanResult) { Map> declarations = new EnumMap<>(Status.class); for (var status : Status.values()) { declarations.put(status, new ArrayList<>()); } - try (var scanResult = scanClasspath(packages)) { - - var types = collectTypes(scanResult); - types.stream() // - .map(Declaration.Type::new) // - .forEach(type -> declarations.get(type.status()).add(type)); + var types = collectTypes(scanResult); + types.stream() // + .map(Declaration.Type::new) // + .forEach(type -> declarations.get(type.status()).add(type)); - collectMethods(scanResult) // - .map(Declaration.Method::new) // - .filter(method -> !declarations.get(method.status()) // - .contains(new Declaration.Type(method.classInfo()))) // - .forEach(method -> { - types.add(method.classInfo()); - declarations.get(method.status()).add(method); - }); + collectMethods(scanResult) // + .map(Declaration.Method::new) // + .filter(method -> !declarations.get(method.status()) // + .contains(new Declaration.Type(method.classInfo()))) // + .forEach(method -> { + types.add(method.classInfo()); + declarations.get(method.status()).add(method); + }); - declarations.values().forEach(list -> list.sort(null)); + declarations.values().forEach(list -> list.sort(null)); - return new ApiReport(types, declarations); - } + return new ApiReport(types, declarations); } - private static ScanResult scanClasspath(String[] packages) { + private static ScanResult scanClasspath() { + // scan all types below "org.junit" package var classGraph = new ClassGraph() // - .acceptPackages(packages) // - .rejectPackages("*.shadow.*") // + .acceptPackages("org.junit") // + .rejectPackages("*.shadow.*", "org.opentest4j.*") // .disableNestedJarScanning() // .enableClassInfo() // .enableMethodInfo() // .enableAnnotationInfo(); // var apiClasspath = System.getProperty("api.classpath"); if (apiClasspath != null) { - classGraph = classGraph.overrideClasspath(apiClasspath); + var paths = Arrays.stream(apiClasspath.split(File.pathSeparator)).map(Path::of).toArray(Path[]::new); + var bootLayer = ModuleLayer.boot(); + var configuration = bootLayer.configuration().resolveAndBind(ModuleFinder.of(), ModuleFinder.of(paths), + Set.of()); + var layer = bootLayer.defineModulesWithOneLoader(configuration, ClassLoader.getPlatformClassLoader()); + classGraph = classGraph.overrideModuleLayers(layer); } return classGraph.scan(); } diff --git a/documentation/src/tools/java/org/junit/api/tools/AsciidocApiReportWriter.java b/documentation/src/tools/java/org/junit/api/tools/AsciidocApiReportWriter.java index 24ff7b9eab1a..0a285d3ffdea 100644 --- a/documentation/src/tools/java/org/junit/api/tools/AsciidocApiReportWriter.java +++ b/documentation/src/tools/java/org/junit/api/tools/AsciidocApiReportWriter.java @@ -17,7 +17,7 @@ */ class AsciidocApiReportWriter extends AbstractApiReportWriter { - private static final String ASCIIDOC_FORMAT = "| %-52s | %-" + NAME_COLUMN_WIDTH + "s | %-12s%n"; + private static final String ASCIIDOC_FORMAT = "|%-" + NAME_COLUMN_WIDTH + "s | %-12s%n"; AsciidocApiReportWriter(ApiReport apiReport) { super(apiReport); @@ -33,6 +33,16 @@ protected String h2(String header) { return "== " + header; } + @Override + protected String h4(String header) { + return "[discrete]%n==== %s".formatted(header); + } + + @Override + protected String h5(String header) { + return "[discrete]%n===== %s".formatted(header); + } + @Override protected String code(String element) { return "`" + element + "`"; @@ -45,16 +55,16 @@ protected String italic(String element) { @Override protected void printDeclarationTableHeader(PrintWriter out) { + out.println("[cols=\"99,1\"]"); out.println("|==="); - out.printf(ASCIIDOC_FORMAT, "Package Name", "Name", "Since"); + out.printf(ASCIIDOC_FORMAT, "Name", "Since"); out.println(); } @Override protected void printDeclarationTableRow(Declaration declaration, PrintWriter out) { out.printf(ASCIIDOC_FORMAT, // - code(declaration.packageName()), // - code(declaration.name()) + " " + italic("(" + declaration.kind() + ")"), // + code(declaration.name().replace(".", ".​")) + " " + italic("(" + declaration.kind() + ")"), // code(declaration.since()) // ); } diff --git a/documentation/src/tools/java/org/junit/api/tools/Declaration.java b/documentation/src/tools/java/org/junit/api/tools/Declaration.java index a6921cce8862..7e8fdd5d1cd9 100644 --- a/documentation/src/tools/java/org/junit/api/tools/Declaration.java +++ b/documentation/src/tools/java/org/junit/api/tools/Declaration.java @@ -24,6 +24,8 @@ sealed interface Declaration extends Comparable { + String moduleName(); + String packageName(); String fullName(); @@ -43,6 +45,11 @@ default int compareTo(Declaration o) { record Type(ClassInfo classInfo) implements Declaration { + @Override + public String moduleName() { + return classInfo.getModuleRef().getName(); + } + @Override public String packageName() { return classInfo.getPackageName(); @@ -55,7 +62,8 @@ public String fullName() { @Override public String name() { - return getShortClassName(classInfo); + var shortClassName = getShortClassName(classInfo); + return classInfo.isAnnotation() ? "@" + shortClassName : shortClassName; } @Override @@ -86,6 +94,11 @@ private AnnotationParameterValueList getParameterValues() { record Method(MethodInfo methodInfo) implements Declaration { + @Override + public String moduleName() { + return classInfo().getModuleRef().getName(); + } + @Override public String packageName() { return classInfo().getPackageName(); @@ -98,14 +111,23 @@ public String fullName() { @Override public String name() { + if (classInfo().isAnnotation()) { + return "@%s(%s=...)".formatted(getShortClassName(classInfo()), methodInfo.getName()); + } + if (methodInfo.isConstructor()) { + return "%s%s".formatted(getShortClassName(classInfo()), methodParameters()); + } return "%s.%s".formatted(getShortClassName(classInfo()), methodSignature()); } private String methodSignature() { - var parameters = Arrays.stream(methodInfo.getParameterInfo()) // + return methodInfo.getName() + methodParameters(); + } + + private String methodParameters() { + return Arrays.stream(methodInfo.getParameterInfo()) // .map(parameterInfo -> parameterInfo.getTypeSignatureOrTypeDescriptor().toStringWithSimpleNames()) // .collect(joining(", ", "(", ")")); - return methodInfo.getName() + parameters; } @Override @@ -152,6 +174,6 @@ private static String getShortClassName(ClassInfo classInfo) { if (typeName.startsWith(packageName + '.')) { typeName = typeName.substring(packageName.length() + 1); } - return typeName; + return typeName.replace('$', '.'); } } diff --git a/documentation/src/tools/java/org/junit/api/tools/HtmlApiReportWriter.java b/documentation/src/tools/java/org/junit/api/tools/HtmlApiReportWriter.java index 56020962d54a..c0f5a237b00a 100644 --- a/documentation/src/tools/java/org/junit/api/tools/HtmlApiReportWriter.java +++ b/documentation/src/tools/java/org/junit/api/tools/HtmlApiReportWriter.java @@ -17,8 +17,8 @@ */ class HtmlApiReportWriter extends AbstractApiReportWriter { - private static final String HTML_HEADER_FORMAT = "\t%s%s%s%n"; - private static final String HTML_ROW_FORMAT = "\t%s%s%s%n"; + private static final String HTML_HEADER_FORMAT = "\t%s%s%n"; + private static final String HTML_ROW_FORMAT = "\t%s%s%n"; HtmlApiReportWriter(ApiReport apiReport) { super(apiReport); @@ -34,6 +34,16 @@ protected String h2(String header) { return "

" + header + "

"; } + @Override + protected String h4(String header) { + return "

" + header + "

"; + } + + @Override + protected String h5(String header) { + return "
" + header + "
"; + } + @Override protected String code(String element) { return "" + element + ""; @@ -52,13 +62,12 @@ protected String paragraph(String element) { @Override protected void printDeclarationTableHeader(PrintWriter out) { out.println(""); - out.printf(HTML_HEADER_FORMAT, "Package Name", "Name", "Since"); + out.printf(HTML_HEADER_FORMAT, "Name", "Since"); } @Override protected void printDeclarationTableRow(Declaration declaration, PrintWriter out) { out.printf(HTML_ROW_FORMAT, // - code(declaration.packageName()), // code(declaration.name()) + " " + italic("(" + declaration.kind() + ")"), // code(declaration.since()) // ); diff --git a/documentation/src/tools/java/org/junit/api/tools/MarkdownApiReportWriter.java b/documentation/src/tools/java/org/junit/api/tools/MarkdownApiReportWriter.java index 385d27d9ae07..458d6c721e8a 100644 --- a/documentation/src/tools/java/org/junit/api/tools/MarkdownApiReportWriter.java +++ b/documentation/src/tools/java/org/junit/api/tools/MarkdownApiReportWriter.java @@ -18,7 +18,7 @@ */ class MarkdownApiReportWriter extends AbstractApiReportWriter { - private static final String MARKDOWN_FORMAT = "%-52s | %-" + NAME_COLUMN_WIDTH + "s | %-12s%n"; + private static final String MARKDOWN_FORMAT = "%-" + NAME_COLUMN_WIDTH + "s | %-12s%n"; MarkdownApiReportWriter(ApiReport apiReport) { super(apiReport); @@ -34,6 +34,16 @@ protected String h2(String header) { return "## " + header; } + @Override + protected String h4(String header) { + return "#### " + header; + } + + @Override + protected String h5(String header) { + return "##### " + header; + } + @Override protected String code(String element) { return "`" + element + "`"; @@ -46,8 +56,8 @@ protected String italic(String element) { @Override protected void printDeclarationTableHeader(PrintWriter out) { - out.printf(MARKDOWN_FORMAT, "Package Name", "Name", "Since"); - out.printf(MARKDOWN_FORMAT, dashes(52), dashes(NAME_COLUMN_WIDTH), dashes(12)); + out.printf(MARKDOWN_FORMAT, "Name", "Since"); + out.printf(MARKDOWN_FORMAT, dashes(NAME_COLUMN_WIDTH), dashes(12)); } private String dashes(int length) { @@ -57,7 +67,6 @@ private String dashes(int length) { @Override protected void printDeclarationTableRow(Declaration declaration, PrintWriter out) { out.printf(MARKDOWN_FORMAT, // - code(declaration.packageName()), // code(declaration.name()) + " " + italic("(" + declaration.kind() + ")"), // code(declaration.since()) // ); From d540e4ff3aeb13a3b3167515efa6ed1ec00b0773 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 7 Mar 2025 14:54:08 +0100 Subject: [PATCH 05/13] Link to correct method --- .../org/junit/platform/commons/support/AnnotationSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ece10478da6e..1f30697db788 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 @@ -165,7 +165,7 @@ public static Optional findAnnotation(AnnotatedElement * @since 1.8 * @see SearchOption * @see #findAnnotation(AnnotatedElement, Class) - * @deprecated Use {@link #findAnnotation(Class, Class, List)} + * @deprecated Use {@link #findAnnotation(AnnotatedElement, Class)} * (for {@code SearchOption.DEFAULT}) or * {@link #findAnnotation(Class, Class, List)} (for * {@code SearchOption.INCLUDE_ENCLOSING_CLASSES}) instead From 1e135b9d37a88bc0319b98ddcfc050fc0cf89a98 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 7 Mar 2025 15:03:42 +0100 Subject: [PATCH 06/13] Create initial 5.12.1 release notes from template --- .../docs/asciidoc/release-notes/index.adoc | 2 + .../release-notes/release-notes-5.12.1.adoc | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index 097e417e7854..12c1eb68b7d8 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-5.12.1.adoc[] + include::{basedir}/release-notes-5.12.0.adoc[] include::{basedir}/release-notes-5.11.4.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc new file mode 100644 index 000000000000..d4c00b9a2517 --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc @@ -0,0 +1,67 @@ +[[release-notes-5.12.1]] +== 5.12.1 + +*Date of Release:* ❓ + +*Scope:* ❓ + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit5-repo}+/milestone/91?closed=1+[5.12.1] milestone page in the JUnit repository +on GitHub. + + +[[release-notes-5.12.1-junit-platform]] +=== JUnit Platform + +[[release-notes-5.12.1-junit-platform-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.12.1-junit-platform-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.12.1-junit-platform-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-5.12.1-junit-jupiter]] +=== JUnit Jupiter + +[[release-notes-5.12.1-junit-jupiter-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.12.1-junit-jupiter-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.12.1-junit-jupiter-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-5.12.1-junit-vintage]] +=== JUnit Vintage + +[[release-notes-5.12.1-junit-vintage-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.12.1-junit-vintage-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.12.1-junit-vintage-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ From 74521ab55ca19269e4cf628ed738d0382a1699c9 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 7 Mar 2025 15:17:20 +0100 Subject: [PATCH 07/13] Introduce `ExtensionContext.getEnclosingTestClasses()` Resolves #4375. --- .../release-notes/release-notes-5.12.1.adoc | 4 +- .../api/extension/ExtensionContext.java | 27 +++++ .../descriptor/ClassExtensionContext.java | 6 ++ .../descriptor/DynamicExtensionContext.java | 8 ++ .../JupiterEngineExtensionContext.java | 8 ++ .../descriptor/MethodBasedTestDescriptor.java | 2 +- .../descriptor/MethodExtensionContext.java | 6 ++ .../TestTemplateExtensionContext.java | 6 ++ .../descriptor/ExtensionContextTests.java | 99 +++++++++++++++---- .../ParameterizedTestExtensionTests.java | 6 ++ 10 files changed, 149 insertions(+), 23 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc index d4c00b9a2517..6a4303cd6e34 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc @@ -45,7 +45,9 @@ on GitHub. [[release-notes-5.12.1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements -* ❓ +* New `ExtensionContext.getEnclosingTestClasses()` method to help with migration away from + `AnnotationSupport.findAnnotation(Class, Class, SearchOption)` (deprecated since 1.12.0) + to `AnnotationSupport.findAnnotation(Class, Class, List)`. [[release-notes-5.12.1-junit-vintage]] 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 a2bfd4db7d80..40c95ef21fc2 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 @@ -40,6 +40,8 @@ *

{@link Extension Extensions} are provided an instance of * {@code ExtensionContext} to perform their work. * + *

This interface is not intended to be implemented by clients. + * * @since 5.0 * @see Store * @see Namespace @@ -129,6 +131,31 @@ public interface ExtensionContext { */ Optional> getTestClass(); + /** + * Get the enclosing test classes of the current test or container. + * + *

This method is useful to look up annotations on nested test classes + * and their enclosing runtime types: + * + *

{@code
+	 * AnnotationSupport.findAnnotation(
+	 *     extensionContext.getRequiredTestClass(),
+	 *     MyAnnotation.class,
+	 *     extensionContext.getEnclosingTestClasses()
+	 * );
+	 * }
+ * + * @return an empty list if there is no class associated with the current + * test or container or when it is not nested; otherwise, a list containing + * the enclosing test classes in order from outermost to innermost; never + * {@code null} + * + * @since 5.12.1 + * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotation(Class, Class, List) + */ + @API(status = EXPERIMENTAL, since = "5.12.1") + List> getEnclosingTestClasses(); + /** * Get the required {@link Class} associated with the current test * or container. diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java index aace0e86e16d..b056a73234bc 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java @@ -12,6 +12,7 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; @@ -68,6 +69,11 @@ public Optional> getTestClass() { return Optional.of(getTestDescriptor().getTestClass()); } + @Override + public List> getEnclosingTestClasses() { + return getTestDescriptor().getEnclosingTestClasses(); + } + @Override public Optional getTestInstanceLifecycle() { return Optional.of(this.lifecycle); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicExtensionContext.java index cd3c292709e2..fc87ef3f3a68 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicExtensionContext.java @@ -10,8 +10,11 @@ package org.junit.jupiter.engine.descriptor; +import static java.util.Collections.emptyList; + import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.TestInstance; @@ -40,6 +43,11 @@ public Optional> getTestClass() { return Optional.empty(); } + @Override + public List> getEnclosingTestClasses() { + return emptyList(); + } + @Override public Optional getTestInstanceLifecycle() { return Optional.empty(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterEngineExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterEngineExtensionContext.java index 6ecd845d6ded..66ba8a94c7ac 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterEngineExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterEngineExtensionContext.java @@ -10,8 +10,11 @@ package org.junit.jupiter.engine.descriptor; +import static java.util.Collections.emptyList; + import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; @@ -43,6 +46,11 @@ public Optional> getTestClass() { return Optional.empty(); } + @Override + public List> getEnclosingTestClasses() { + return emptyList(); + } + @Override public Optional getTestInstanceLifecycle() { return Optional.empty(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java index 3a5b785591f8..5dc853d86484 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java @@ -106,7 +106,7 @@ public Function> getResou getTestMethod())); } - private List> getEnclosingTestClasses() { + List> getEnclosingTestClasses() { return getParent() // .filter(ClassBasedTestDescriptor.class::isInstance) // .map(ClassBasedTestDescriptor.class::cast) // diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java index a6d983e7196b..24cdd6914eb3 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java @@ -12,6 +12,7 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; @@ -51,6 +52,11 @@ public Optional> getTestClass() { return Optional.of(getTestDescriptor().getTestClass()); } + @Override + public List> getEnclosingTestClasses() { + return getTestDescriptor().getEnclosingTestClasses(); + } + @Override public Optional getTestInstanceLifecycle() { return getParent().flatMap(ExtensionContext::getTestInstanceLifecycle); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java index ea6df34d7436..5fa74917714b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java @@ -12,6 +12,7 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.TestInstance.Lifecycle; @@ -47,6 +48,11 @@ public Optional> getTestClass() { return Optional.of(getTestDescriptor().getTestClass()); } + @Override + public List> getEnclosingTestClasses() { + return getTestDescriptor().getEnclosingTestClasses(); + } + @Override public Optional getTestInstanceLifecycle() { return getParent().flatMap(ExtensionContext::getTestInstanceLifecycle); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java index 48682ff17e7a..62d40fc3e966 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java @@ -39,6 +39,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Named; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.Extension; @@ -111,33 +112,63 @@ void fromJupiterEngineDescriptor() { } @Test - @SuppressWarnings("resource") void fromClassTestDescriptor() { var nestedClassDescriptor = nestedClassDescriptor(); var outerClassDescriptor = outerClassDescriptor(nestedClassDescriptor); + var doublyNestedClassDescriptor = doublyNestedClassDescriptor(); + var methodTestDescriptor = nestedMethodDescriptor(); + nestedClassDescriptor.addChild(doublyNestedClassDescriptor); + nestedClassDescriptor.addChild(methodTestDescriptor); var outerExtensionContext = new ClassExtensionContext(null, null, outerClassDescriptor, configuration, extensionRegistry, null); // @formatter:off assertAll("outerContext", - () -> assertThat(outerExtensionContext.getElement()).contains(OuterClass.class), - () -> assertThat(outerExtensionContext.getTestClass()).contains(OuterClass.class), + () -> assertThat(outerExtensionContext.getElement()).contains(OuterClassTestCase.class), + () -> assertThat(outerExtensionContext.getTestClass()).contains(OuterClassTestCase.class), () -> assertThat(outerExtensionContext.getTestInstance()).isEmpty(), () -> assertThat(outerExtensionContext.getTestMethod()).isEmpty(), - () -> assertThat(outerExtensionContext.getRequiredTestClass()).isEqualTo(OuterClass.class), + () -> assertThat(outerExtensionContext.getRequiredTestClass()).isEqualTo(OuterClassTestCase.class), () -> assertThrows(PreconditionViolationException.class, outerExtensionContext::getRequiredTestInstance), () -> assertThrows(PreconditionViolationException.class, outerExtensionContext::getRequiredTestMethod), () -> assertThat(outerExtensionContext.getDisplayName()).isEqualTo(outerClassDescriptor.getDisplayName()), () -> assertThat(outerExtensionContext.getParent()).isEmpty(), () -> assertThat(outerExtensionContext.getExecutionMode()).isEqualTo(ExecutionMode.SAME_THREAD), - () -> assertThat(outerExtensionContext.getExtensions(PreInterruptCallback.class)).isEmpty() + () -> assertThat(outerExtensionContext.getExtensions(PreInterruptCallback.class)).isEmpty(), + () -> assertThat(outerExtensionContext.getEnclosingTestClasses()).isEmpty() ); // @formatter:on var nestedExtensionContext = new ClassExtensionContext(outerExtensionContext, null, nestedClassDescriptor, configuration, extensionRegistry, null); - assertThat(nestedExtensionContext.getParent()).containsSame(outerExtensionContext); + // @formatter:off + assertAll("nestedContext", + () -> assertThat(nestedExtensionContext.getParent()).containsSame(outerExtensionContext), + () -> assertThat(nestedExtensionContext.getTestClass()).contains(OuterClassTestCase.NestedClass.class), + () -> assertThat(nestedExtensionContext.getEnclosingTestClasses()).containsExactly(OuterClassTestCase.class) + ); + // @formatter:on + + var doublyNestedExtensionContext = new ClassExtensionContext(nestedExtensionContext, null, + doublyNestedClassDescriptor, configuration, extensionRegistry, null); + // @formatter:off + assertAll("doublyNestedContext", + () -> assertThat(doublyNestedExtensionContext.getParent()).containsSame(nestedExtensionContext), + () -> assertThat(doublyNestedExtensionContext.getTestClass()).contains(OuterClassTestCase.NestedClass.DoublyNestedClass.class), + () -> assertThat(doublyNestedExtensionContext.getEnclosingTestClasses()).containsExactly(OuterClassTestCase.class, OuterClassTestCase.NestedClass.class) + ); + // @formatter:on + + var methodExtensionContext = new MethodExtensionContext(nestedExtensionContext, null, methodTestDescriptor, + configuration, extensionRegistry, new OpenTest4JAwareThrowableCollector()); + // @formatter:off + assertAll("methodContext", + () -> assertThat(methodExtensionContext.getParent()).containsSame(nestedExtensionContext), + () -> assertThat(methodExtensionContext.getTestClass()).contains(OuterClassTestCase.NestedClass.class), + () -> assertThat(methodExtensionContext.getEnclosingTestClasses()).containsExactly(OuterClassTestCase.class) + ); + // @formatter:on } @Test @@ -154,7 +185,6 @@ void ExtensionContext_With_ExtensionRegistry_getExtensions() { } @Test - @SuppressWarnings("resource") void tagsCanBeRetrievedInExtensionContext() { var nestedClassDescriptor = nestedClassDescriptor(); var outerClassDescriptor = outerClassDescriptor(nestedClassDescriptor); @@ -174,20 +204,19 @@ void tagsCanBeRetrievedInExtensionContext() { var methodExtensionContext = new MethodExtensionContext(outerExtensionContext, null, methodTestDescriptor, configuration, extensionRegistry, new OpenTest4JAwareThrowableCollector()); - methodExtensionContext.setTestInstances(DefaultTestInstances.of(new OuterClass())); + methodExtensionContext.setTestInstances(DefaultTestInstances.of(new OuterClassTestCase())); assertThat(methodExtensionContext.getTags()).containsExactlyInAnyOrder("outer-tag", "method-tag"); assertThat(methodExtensionContext.getRoot()).isSameAs(outerExtensionContext); } @Test - @SuppressWarnings("resource") void fromMethodTestDescriptor() { var methodTestDescriptor = methodDescriptor(); var classTestDescriptor = outerClassDescriptor(methodTestDescriptor); var engineDescriptor = new JupiterEngineDescriptor(UniqueId.forEngine("junit-jupiter"), configuration); engineDescriptor.addChild(classTestDescriptor); - Object testInstance = new OuterClass(); + Object testInstance = new OuterClassTestCase(); var testMethod = methodTestDescriptor.getTestMethod(); var engineExtensionContext = new JupiterEngineExtensionContext(null, engineDescriptor, configuration, @@ -201,10 +230,11 @@ void fromMethodTestDescriptor() { // @formatter:off assertAll("methodContext", () -> assertThat(methodExtensionContext.getElement()).contains(testMethod), - () -> assertThat(methodExtensionContext.getTestClass()).contains(OuterClass.class), + () -> assertThat(methodExtensionContext.getTestClass()).contains(OuterClassTestCase.class), + () -> assertThat(methodExtensionContext.getEnclosingTestClasses()).isEmpty(), () -> assertThat(methodExtensionContext.getTestInstance()).contains(testInstance), () -> assertThat(methodExtensionContext.getTestMethod()).contains(testMethod), - () -> assertThat(methodExtensionContext.getRequiredTestClass()).isEqualTo(OuterClass.class), + () -> assertThat(methodExtensionContext.getRequiredTestClass()).isEqualTo(OuterClassTestCase.class), () -> assertThat(methodExtensionContext.getRequiredTestInstance()).isEqualTo(testInstance), () -> assertThat(methodExtensionContext.getRequiredTestMethod()).isEqualTo(testMethod), () -> assertThat(methodExtensionContext.getDisplayName()).isEqualTo(methodTestDescriptor.getDisplayName()), @@ -359,7 +389,7 @@ void usingStore() { extensionRegistry, null); var childContext = new MethodExtensionContext(parentContext, null, methodTestDescriptor, configuration, extensionRegistry, new OpenTest4JAwareThrowableCollector()); - childContext.setTestInstances(DefaultTestInstances.of(new OuterClass())); + childContext.setTestInstances(DefaultTestInstances.of(new OuterClassTestCase())); var childStore = childContext.getStore(Namespace.GLOBAL); var parentStore = parentContext.getStore(Namespace.GLOBAL); @@ -430,13 +460,18 @@ void configurationParameter(Function> getTestClass() { return Optional.empty(); } + @Override + public List> getEnclosingTestClasses() { + return List.of(); + } + @Override public Optional getTestInstanceLifecycle() { return Optional.empty(); From 062d3fa175d94010c24054fb44b2566955ba95ae Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 10 Mar 2025 16:06:05 +0100 Subject: [PATCH 08/13] Remove internal packages from API reports (cherry picked from commit e269a1c2febfa6ade7d8c775fe47d51aa6ea8366) --- .../src/tools/java/org/junit/api/tools/ApiReportGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java b/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java index d256652de1b2..01e6b7832988 100644 --- a/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java +++ b/documentation/src/tools/java/org/junit/api/tools/ApiReportGenerator.java @@ -135,7 +135,8 @@ private static ScanResult scanClasspath() { // scan all types below "org.junit" package var classGraph = new ClassGraph() // .acceptPackages("org.junit") // - .rejectPackages("*.shadow.*", "org.opentest4j.*") // + .rejectPackages("*.shadow.*", "org.opentest4j.*", "org.junit.platform.commons.logging", + "org.junit.platform.commons.util") // .disableNestedJarScanning() // .enableClassInfo() // .enableMethodInfo() // From 1a1a67daee1507ae85a25ec0f57bce98d6824b39 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Mon, 10 Mar 2025 12:25:13 +0100 Subject: [PATCH 09/13] Set stable module name for the standalone JAR file Closes #4079 (cherry picked from commit b7fe31db0b5b079a6ceb0690938a539accc49510) --- .../junit-platform-console-standalone.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts index a15f463a4d04..99ed213d9837 100644 --- a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts +++ b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts @@ -27,6 +27,7 @@ val vintageVersion: String by project tasks { jar { manifest { + attributes("Automatic-Module-Name" to "org.junit.platform.console.standalone") attributes("Main-Class" to "org.junit.platform.console.ConsoleLauncher") } } From bea821d69ae8848aa21f7ee10692c6185abfc9ac Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 11 Mar 2025 14:31:56 +0100 Subject: [PATCH 10/13] Fix Javadoc formatting (cherry picked from commit d18df3a47e7f4de9f688f442eddb7046d948fcc9) --- .../platform/launcher/core/EngineDiscoveryOrchestrator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java index 09c895a69684..0b3d1be891ad 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java @@ -86,8 +86,8 @@ public LauncherDiscoveryResult discover(LauncherDiscoveryRequest request, Phase * filters} and {@linkplain PostDiscoveryFilter post-discovery filters} and * {@linkplain TestDescriptor#prune() prunes} the resulting test tree. * - * Note: The test descriptors in the discovery result can safely be used as - * non-root descriptors. Engine-test descriptor entries are pruned from + *

Note: The test descriptors in the discovery result can safely be used + * as non-root descriptors. Engine-test descriptor entries are pruned from * the returned result. As such execution by * {@link EngineExecutionOrchestrator#execute(LauncherDiscoveryResult, EngineExecutionListener)} * will not emit start or emit events for engines without tests. From 1044e2c63c435f735ab78dbbca09e78b13fb5f80 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 13 Mar 2025 10:03:31 +0100 Subject: [PATCH 11/13] Move entry to 5.12.1 release notes (cherry picked from commit 65827ea4aedf0080483ab219b11a87741ca9bc6a) --- .../src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc index 6a4303cd6e34..bbf7cb7bcabf 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc @@ -21,7 +21,9 @@ on GitHub. [[release-notes-5.12.1-junit-platform-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes -* ❓ +* Set stable module name `org.junit.platform.console.standalone` for the + `junit-platform-console-standalone` artifact, superseding the unstable name generated + from the name of the JAR file when putting the artifact on the module path. [[release-notes-5.12.1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements From e28ad4a89047da0aca6aca32b0e45ac8309954e1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 13 Mar 2025 10:08:24 +0100 Subject: [PATCH 12/13] Finalize 5.12.1 release notes --- .../release-notes/release-notes-5.12.1.adoc | 39 ++----------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc index bbf7cb7bcabf..f41490897fb5 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc @@ -1,9 +1,9 @@ [[release-notes-5.12.1]] == 5.12.1 -*Date of Release:* ❓ +*Date of Release:* March 14, 2025 -*Scope:* ❓ +*Scope:* Bug fixes and enhancements since 5.12.0 For a complete list of all _closed_ issues and pull requests for this release, consult the link:{junit5-repo}+/milestone/91?closed=1+[5.12.1] milestone page in the JUnit repository @@ -13,11 +13,6 @@ on GitHub. [[release-notes-5.12.1-junit-platform]] === JUnit Platform -[[release-notes-5.12.1-junit-platform-bug-fixes]] -==== Bug Fixes - -* ❓ - [[release-notes-5.12.1-junit-platform-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes @@ -25,25 +20,10 @@ on GitHub. `junit-platform-console-standalone` artifact, superseding the unstable name generated from the name of the JAR file when putting the artifact on the module path. -[[release-notes-5.12.1-junit-platform-new-features-and-improvements]] -==== New Features and Improvements - -* ❓ - [[release-notes-5.12.1-junit-jupiter]] === JUnit Jupiter -[[release-notes-5.12.1-junit-jupiter-bug-fixes]] -==== Bug Fixes - -* ❓ - -[[release-notes-5.12.1-junit-jupiter-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - [[release-notes-5.12.1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements @@ -55,17 +35,4 @@ on GitHub. [[release-notes-5.12.1-junit-vintage]] === JUnit Vintage -[[release-notes-5.12.1-junit-vintage-bug-fixes]] -==== Bug Fixes - -* ❓ - -[[release-notes-5.12.1-junit-vintage-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - -[[release-notes-5.12.1-junit-vintage-new-features-and-improvements]] -==== New Features and Improvements - -* ❓ +No changes. From ba9c9ae111f5f06645ebcda2bb831c8e093cc002 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 14 Mar 2025 14:07:50 +0100 Subject: [PATCH 13/13] Release 5.12.1 --- README.md | 2 +- gradle.properties | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index be040f0b3e7c..5b61d030dd0a 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This repository is the home of _JUnit 5_. ## Latest Releases -- General Availability (GA): [JUnit 5.12.0](https://github.com/junit-team/junit5/releases/tag/r5.12.0) (February 21, 2025) +- General Availability (GA): [JUnit 5.12.1](https://github.com/junit-team/junit5/releases/tag/r5.12.1) (March 14, 2025) - Preview (Milestone/Release Candidate): N/A ## Documentation diff --git a/gradle.properties b/gradle.properties index 85e568f178ea..493b1f3d62e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,13 @@ group = org.junit -version = 5.12.1-SNAPSHOT +version = 5.12.1 jupiterGroup = org.junit.jupiter platformGroup = org.junit.platform -platformVersion = 1.12.1-SNAPSHOT +platformVersion = 1.12.1 vintageGroup = org.junit.vintage -vintageVersion = 5.12.1-SNAPSHOT +vintageVersion = 5.12.1 # We need more metaspace due to apparent memory leak in Asciidoctor/JRuby # The exports are needed due to https://github.com/diffplug/spotless/issues/834 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy