Skip to content

Commit c555910

Browse files
authored
Merge branch 'main' into feature/4434
2 parents a2746b3 + bbaa8cd commit c555910

File tree

9 files changed

+191
-16
lines changed

9 files changed

+191
-16
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This repository is the home of _JUnit 5_.
1212

1313
## Latest Releases
1414

15-
- General Availability (GA): [JUnit 5.12.1](https://github.com/junit-team/junit5/releases/tag/r5.12.1) (March 14, 2025)
15+
- General Availability (GA): [JUnit 5.12.2](https://github.com/junit-team/junit5/releases/tag/r5.12.2) (April 11, 2025)
1616
- Preview (Milestone/Release Candidate): [JUnit 5.13.0-M2](https://github.com/junit-team/junit5/releases/tag/r5.13.0-M2) (March 24, 2025)
1717

1818
## Documentation

Diff for: documentation/src/docs/asciidoc/link-attributes.adoc

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ endif::[]
2525
:ClasspathResourceSelector: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/ClasspathResourceSelector.html[ClasspathResourceSelector]
2626
:ClasspathRootSelector: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/ClasspathRootSelector.html[ClasspathRootSelector]
2727
:ClassSelector: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/ClassSelector.html[ClassSelector]
28+
:DiscoveryIssue: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/DiscoveryIssue.html[DiscoveryIssue]
29+
:DiscoveryIssueReporter: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/support/discovery/DiscoveryIssueReporter.html[DiscoveryIssueReporter]
2830
:DirectorySelector: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/DirectorySelector.html[DirectorySelector]
2931
:DiscoverySelectors: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/DiscoverySelectors.html[DiscoverySelectors]
3032
:DiscoverySelectors_selectClasspathResource: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/DiscoverySelectors.html#selectClasspathResource(java.lang.String)[selectClasspathResource]
@@ -40,6 +42,7 @@ endif::[]
4042
:DiscoverySelectors_selectPackage: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/DiscoverySelectors.html#selectPackage(java.lang.String)[selectPackage]
4143
:DiscoverySelectors_selectUniqueId: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/DiscoverySelectors.html#selectUniqueId(java.lang.String)[selectUniqueId]
4244
:DiscoverySelectors_selectUri: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/DiscoverySelectors.html#selectUri(java.lang.String)[selectUri]
45+
:EngineDiscoveryListener: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/EngineDiscoveryListener.html[EngineDiscoveryListener]
4346
:EngineDiscoveryRequest: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/EngineDiscoveryRequest.html[EngineDiscoveryRequest]
4447
:FileSelector: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/discovery/FileSelector.html[FileSelector]
4548
:HierarchicalTestEngine: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/support/hierarchical/HierarchicalTestEngine.html[HierarchicalTestEngine]
@@ -57,6 +60,7 @@ endif::[]
5760
:TestEngine: {javadoc-root}/org.junit.platform.engine/org/junit/platform/engine/TestEngine.html[TestEngine]
5861
// Platform Launcher API
5962
:junit-platform-launcher: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/package-summary.html[junit-platform-launcher]
63+
:DiscoveryIssueException: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/core/DiscoveryIssueException.html[DiscoveryIssueException]
6064
:Launcher: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/Launcher.html[Launcher]
6165
:LauncherConfig: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/core/LauncherConfig.html[LauncherConfig]
6266
:LauncherDiscoveryListener: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherDiscoveryListener.html[LauncherDiscoveryListener]

Diff for: documentation/src/docs/asciidoc/release-notes/index.adoc

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ include::{basedir}/release-notes-5.13.0-M2.adoc[]
2323

2424
include::{basedir}/release-notes-5.13.0-M1.adoc[]
2525

26+
include::{basedir}/release-notes-5.12.2.adoc[]
27+
2628
include::{basedir}/release-notes-5.12.1.adoc[]
2729

2830
include::{basedir}/release-notes-5.12.0.adoc[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[[release-notes-5.12.2]]
2+
== 5.12.2
3+
4+
*Date of Release:* April 11, 2025
5+
6+
*Scope:* Bug fixes and enhancements since 5.12.1
7+
8+
For a complete list of all _closed_ issues and pull requests for this release, consult the
9+
link:{junit5-repo}+/milestone/95?closed=1+[5.12.2] milestone page in the JUnit repository
10+
on GitHub.
11+
12+
13+
[[release-notes-5.12.2-junit-platform]]
14+
=== JUnit Platform
15+
16+
No changes.
17+
18+
19+
[[release-notes-5.12.2-junit-jupiter]]
20+
=== JUnit Jupiter
21+
22+
[[release-notes-5.12.2-junit-jupiter-bug-fixes]]
23+
==== Bug Fixes
24+
25+
* Fix handling of `CleanupMode.ON_SUCCESS` with `@TempDir` that caused no temporary
26+
directories (using that mode) to be deleted after the first failure even if the
27+
corresponding tests passed.
28+
29+
30+
[[release-notes-5.12.2-junit-vintage]]
31+
=== JUnit Vintage
32+
33+
No changes.

Diff for: documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0-M3.adoc

+32-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@ repository on GitHub.
3535
and
3636
<<../user-guide/index.adoc#launcher-api-managing-state-across-test-engines, request-scoped>>
3737
resources.
38+
* Introduce a mechanism for `TestEngine` implementations to report issues encountered
39+
during test discovery. If an engine reports a `DiscoveryIssue` with a `Severity` equal
40+
to or higher than a configurable critical severity, its tests will not be executed.
41+
Instead, the engine will be reported as failed during execution with a failure message
42+
listing all critical issues. Non-critical issues will be logged but will not prevent the
43+
engine from executing its tests. The critical severity can be configured via a new
44+
configuration parameter and, currently, defaults to `ERROR`. Please refer to the
45+
<<../user-guide/index.adoc#running-tests-discovery-issues, User Guide>> for details.
46+
+
47+
If you're a test engine maintainer, please see the
48+
<<../user-guide/index.adoc#test-engines-discovery-issues, User Guide>> for details on how
49+
to start reporting discovery issues.
50+
* Start reporting discovery issues for problematic `@Suite` classes:
51+
- Invalid `@Suite` class declarations (for example, when `private`)
52+
- Invalid `@BeforeSuite`/`@AfterSuite` method declarations (for example, when not
53+
`static`)
54+
- Cyclic dependencies between `@Suite` classes
3855

3956
* Introduce feature flag for auto-closing `AutoCloseable` in Jupiter's ExtensionContext.Store
4057

@@ -55,10 +72,21 @@ repository on GitHub.
5572
[[release-notes-5.13.0-M3-junit-jupiter-new-features-and-improvements]]
5673
==== New Features and Improvements
5774

58-
* Return types of `@TestFactory` methods are now validated during discovery rather than
59-
during execution. Invalid `@TestFactory` methods are no longer executed but reported as
60-
discovery issues for consistency with how `@Test` and `@TestTemplate` methods are
61-
handled.
75+
* Start reporting discovery issues for potentially problematic test classes:
76+
- Invalid `@Test` and `@TestTemplate` method declarations (for example, when return
77+
type is not `void`)
78+
- Invalid `@TestFactory` methods (for example, when return type is invalid)
79+
- Multiple method-level annotations (for example, `@Test` and `@TestTemplate`)
80+
- Invalid test class and `@Nested` class declarations (for example, `static` `@Nested`
81+
classes)
82+
- Potentially missing `@Nested` annotations (for example, non-abstract inner classes
83+
that contain test methods)
84+
- Invalid lifecycle method declarations (for example, when `private`)
85+
- Invalid `@Tag` syntax
86+
- Blank `@DisplayName` declarations
87+
- Blank `@SentenceFragment` declarations
88+
- `@BeforeParameterizedClassInvocation` and `@AfterParameterizedClassInvocation`
89+
methods declared in non-parameterized test classes
6290

6391

6492
[[release-notes-5.13.0-M3-junit-vintage]]

Diff for: documentation/src/docs/asciidoc/user-guide/advanced-topics/engines.adoc

+19
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,22 @@ compatibility with build tools and IDEs:
120120
siblings or other nodes that are required for the execution of the selected tests.
121121
* `TestEngines` _should_ support <<running-tests-tags, tagging>> tests and containers so
122122
that tag filters can be applied when discovering tests.
123+
124+
[[test-engines-discovery-issues]]
125+
==== Reporting Discovery Issues
126+
127+
Test engines should report <<running-tests-discovery-issues, discovery issues>> if they
128+
encounter any problems or potential misconfigurations during test discovery. This is
129+
especially important if the issue could lead to tests not being executed at all or only
130+
partially.
131+
132+
In order to report a `{DiscoveryIssue}`, a test engine should call the
133+
`issueEncountered()` method on the `{EngineDiscoveryListener}` available via the
134+
`{EngineDiscoveryRequest}` passed to its `discover()` method. Rather than passing the
135+
listener around, the `{DiscoveryIssueReporter}` interface should be used. It also provides
136+
a way to create a `Condition` that reports a discovery issue if its check fails and may
137+
be used as a `Predicate` or `Consumer`. Please refer to the implementations of the
138+
<<test-engines-junit, test engines provided by JUnit>> for examples.
139+
140+
Moreover, <<testkit-engine-discovery, Engine Test Kit>> provides a way to write tests for
141+
reported discovery issues.

Diff for: documentation/src/docs/asciidoc/user-guide/running-tests.adoc

+37
Original file line numberDiff line numberDiff line change
@@ -1288,3 +1288,40 @@ never be excluded.
12881288

12891289
In addition, all elements prior to and including the first call from the JUnit Platform
12901290
Launcher will be removed.
1291+
1292+
[[running-tests-discovery-issues]]
1293+
=== Discovery Issues
1294+
1295+
Test engines may encounter issues during test discovery. For example, the declaration of a
1296+
test class or method may be invalid. To avoid such issues from going unnoticed, the JUnit
1297+
Platform provides a <<test-engines-discovery-issues, mechanism for test engines>> to
1298+
report them with different severity levels:
1299+
1300+
INFO::
1301+
Indicates that the engine encountered something that could be potentially problematic, but
1302+
could also happen due to a valid setup or configuration.
1303+
1304+
WARNING::
1305+
Indicates that the engine encountered something that is problematic and might lead to
1306+
unexpected behavior or will be removed or changed in a future release.
1307+
1308+
ERROR::
1309+
Indicates that the engine encountered something that is definitely problematic and will
1310+
lead to unexpected behavior.
1311+
1312+
If an engine reports an issue with a severity equal to or higher than a configurable
1313+
_critical_ severity, its tests will not be executed. Instead, the engine will be reported
1314+
as failed during execution with a `{DiscoveryIssueException}` listing all critical issues.
1315+
Non-critical issues will be logged but will not prevent the engine from executing its
1316+
tests. The `junit.platform.discovery.issue.severity.critical`
1317+
<<running-tests-config-params, configuration parameter>> can be used to set the critical
1318+
severity level. Currently, the default value is `ERROR` but it may be changed in a future
1319+
release.
1320+
1321+
TIP: To surface all discovery issues in your project, it is recommended to set the
1322+
`junit.platform.discovery.issue.severity.critical` configuration parameter to `INFO`.
1323+
1324+
In addition, registered `{LauncherDiscoveryListener}` implementations can receive
1325+
discovery issues via the `issueEncountered()` method. This allows IDEs and build tools to
1326+
report issues to the user in a more user-friendly way. For example, IDEs may choose to
1327+
display all issues in a list or table.

Diff for: junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ public void beforeEach(ExtensionContext context) {
128128
}
129129

130130
private static void installFailureTracker(ExtensionContext context) {
131+
context.getParent() //
132+
.filter(parentContext -> !context.getRoot().equals(parentContext)) //
133+
.ifPresent(parentContext -> installFailureTracker(context, parentContext));
134+
}
135+
136+
private static void installFailureTracker(ExtensionContext context, ExtensionContext parentContext) {
131137
context.getStore(NAMESPACE).put(FAILURE_TRACKER, (AutoCloseable) () -> context.getParent() //
132138
.ifPresent(parentContext -> {
133139
if (selfOrChildFailed(context)) {
@@ -285,7 +291,11 @@ static CloseablePath createTempDir(TempDirFactory factory, CleanupMode cleanupMo
285291

286292
private static boolean selfOrChildFailed(ExtensionContext context) {
287293
return context.getExecutionException().isPresent() //
288-
|| context.getStore(NAMESPACE).getOrDefault(CHILD_FAILED, Boolean.class, false);
294+
|| getContextSpecificStore(context).getOrDefault(CHILD_FAILED, Boolean.class, false);
295+
}
296+
297+
private static ExtensionContext.Store getContextSpecificStore(ExtensionContext context) {
298+
return context.getStore(NAMESPACE.append(context));
289299
}
290300

291301
static class CloseablePath implements AutoCloseable {

Diff for: jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java

+52-10
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import java.util.logging.Level;
2828
import java.util.logging.LogRecord;
2929

30-
import org.junit.jupiter.api.AfterAll;
30+
import org.junit.jupiter.api.AfterEach;
3131
import org.junit.jupiter.api.MethodOrderer;
3232
import org.junit.jupiter.api.Nested;
3333
import org.junit.jupiter.api.Order;
@@ -60,6 +60,7 @@ class TempDirFieldTests {
6060
private static Path alwaysFieldDir;
6161
private static Path onSuccessFailingFieldDir;
6262
private static Path onSuccessPassingFieldDir;
63+
private static Path onSuccessPassingParameterDir;
6364

6465
/**
6566
* Ensure the cleanup mode defaults to ALWAYS for fields.
@@ -152,6 +153,14 @@ void cleanupModeOnSuccessFailingField() {
152153
assertThat(onSuccessFailingFieldDir).exists();
153154
}
154155

156+
@Test
157+
void cleanupModeOnSuccessFailingThenPassingField() {
158+
executeTests(selectClass(OnSuccessFailingFieldCase.class), selectClass(OnSuccessPassingFieldCase.class));
159+
160+
assertThat(onSuccessFailingFieldDir).exists();
161+
assertThat(onSuccessPassingFieldDir).doesNotExist();
162+
}
163+
155164
/**
156165
* Ensure that ON_SUCCESS cleanup modes are obeyed for static fields when tests are failing.
157166
* <p/>
@@ -174,21 +183,20 @@ void cleanupModeOnSuccessFailingStaticField() {
174183
*/
175184
@Test
176185
void cleanupModeOnSuccessFailingStaticFieldWithNesting() {
177-
LauncherDiscoveryRequest request = request()//
178-
.selectors(selectClass(OnSuccessFailingStaticFieldWithNestingCase.class))//
179-
.build();
180-
executeTests(request);
186+
executeTestsForClass(OnSuccessFailingStaticFieldWithNestingCase.class);
181187

182188
assertThat(onSuccessFailingFieldDir).exists();
189+
assertThat(onSuccessPassingParameterDir).doesNotExist();
183190
}
184191

185-
@AfterAll
186-
static void afterAll() throws IOException {
192+
@AfterEach
193+
void deleteTempDirs() throws IOException {
187194
deleteIfNotNullAndExists(defaultFieldDir);
188195
deleteIfNotNullAndExists(neverFieldDir);
189196
deleteIfNotNullAndExists(alwaysFieldDir);
190197
deleteIfNotNullAndExists(onSuccessFailingFieldDir);
191198
deleteIfNotNullAndExists(onSuccessPassingFieldDir);
199+
deleteIfNotNullAndExists(onSuccessPassingParameterDir);
192200
}
193201

194202
static void deleteIfNotNullAndExists(Path dir) throws IOException {
@@ -286,13 +294,21 @@ static class OnSuccessFailingStaticFieldWithNestingCase {
286294
static Path onSuccessFailingFieldDir;
287295

288296
@Nested
297+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
289298
class NestedTestCase {
290299

291300
@Test
292-
void test() {
301+
@Order(1)
302+
void failingTest() {
293303
TempDirFieldTests.onSuccessFailingFieldDir = onSuccessFailingFieldDir;
294304
fail();
295305
}
306+
307+
@Test
308+
@Order(2)
309+
void passingTest(@TempDir(cleanup = ON_SUCCESS) Path tempDir) {
310+
TempDirFieldTests.onSuccessPassingParameterDir = tempDir;
311+
}
296312
}
297313
}
298314

@@ -400,8 +416,16 @@ void cleanupModeOnSuccessFailingParameter() {
400416
assertThat(onSuccessFailingParameterDir).exists();
401417
}
402418

403-
@AfterAll
404-
static void afterAll() throws IOException {
419+
@Test
420+
void cleanupModeOnSuccessFailingThenPassingParameter() {
421+
executeTestsForClass(OnSuccessFailingThenPassingParameterCase.class);
422+
423+
assertThat(onSuccessFailingParameterDir).exists();
424+
assertThat(onSuccessPassingParameterDir).doesNotExist();
425+
}
426+
427+
@AfterEach
428+
void deleteTempDirs() throws IOException {
405429
TempDirFieldTests.deleteIfNotNullAndExists(defaultParameterDir);
406430
TempDirFieldTests.deleteIfNotNullAndExists(neverParameterDir);
407431
TempDirFieldTests.deleteIfNotNullAndExists(alwaysParameterDir);
@@ -457,6 +481,24 @@ void testOnSuccessFailingParameter(@TempDir(cleanup = ON_SUCCESS) Path onSuccess
457481
}
458482
}
459483

484+
@SuppressWarnings({ "JUnitMalformedDeclaration", "NewClassNamingConvention" })
485+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
486+
static class OnSuccessFailingThenPassingParameterCase {
487+
488+
@Test
489+
@Order(1)
490+
void testOnSuccessFailingParameter(@TempDir(cleanup = ON_SUCCESS) Path onSuccessFailingParameterDir) {
491+
TempDirParameterTests.onSuccessFailingParameterDir = onSuccessFailingParameterDir;
492+
fail();
493+
}
494+
495+
@Test
496+
@Order(2)
497+
void testOnSuccessPassingParameter(@TempDir(cleanup = ON_SUCCESS) Path onSuccessPassingParameterDir) {
498+
TempDirParameterTests.onSuccessPassingParameterDir = onSuccessPassingParameterDir;
499+
}
500+
}
501+
460502
}
461503

462504
@Nested

0 commit comments

Comments
 (0)