Skip to content

Fixes #3264 : tests inside @Suite incorrectly classified as flakes - #3342

Merged
olamy merged 2 commits into
apache:masterfrom
mirkoalicastro:fix/suite-flake-misclassification
Aug 6, 2026
Merged

olamy merged 2 commits into
apache:masterfrom
mirkoalicastro:fix/suite-flake-misclassification

Conversation

@mirkoalicastro

@mirkoalicastro mirkoalicastro commented Apr 8, 2026 •

Copy link
Copy Markdown
Contributor

When rerunFailingTestsCount is used with JUnit Platform @Suite, tests from different classes that share a method name are merged under the Suite class name. It causes real failures to be misclassified as flakes. With the changes in the PR, findTopParent() now stops at engine boundaries (parents with no ClassSource), correctly attributing tests to their actual class while preserving @Nested.

  • New unit test added
  • Verified with the small project shared in the original issue: build correctly fails after fix

Following this checklist to help us incorporate your contribution quickly and easily:

  • Each commit in the pull request should have a meaningful subject line and body.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Run mvn clean install to make sure basic checks pass. A more thorough check will be performed on your pull request automatically.
  • You have run the integration tests successfully (mvn -Prun-its clean install).

If your pull request is about ~20 lines of code you don't need to sign an
Individual Contributor License Agreement if you are unsure
please ask on the developers list.

To make clear that you license your contribution under
the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.

@mirkoalicastro
mirkoalicastro marked this pull request as ready for review April 8, 2026 19:14
@mirkoalicastro
mirkoalicastro marked this pull request as draft April 8, 2026 19:19
@mirkoalicastro
mirkoalicastro force-pushed the fix/suite-flake-misclassification branch from fabffc2 to 878db1d Compare April 9, 2026 08:53
@mirkoalicastro
mirkoalicastro marked this pull request as ready for review April 9, 2026 08:53
@mirkoalicastro

Copy link
Copy Markdown
Contributor Author

Hi @olamy , any chance you could have a look at this? πŸ™

@mirkoalicastro

Copy link
Copy Markdown
Contributor Author

@olamy it looks that there are some failures - unrelated to the changes. Would it be fine to proceed?

@olamy

olamy commented Jun 2, 2026

Copy link
Copy Markdown
Member

I have the same failure locally using

Apache Maven 3.9.15 (98b2cdbfdb5f1ac8781f537ea9acccaed7922349)
Maven home: /home/olamy/.sdkman/candidates/maven/current
Java version: 21.0.9, vendor: Eclipse Adoptium, runtime: /home/olamy/.sdkman/candidates/java/21.0.9-tem
Default locale: en_AU, platform encoding: UTF-8
OS name: "linux", version: "6.18.7-76061807-generic", arch: "amd64", family: "unix"

Output

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 11.15 s <<< FAILURE! -- in org.apache.maven.surefire.its.CucumberIT
[ERROR] org.apache.maven.surefire.its.CucumberIT.simpleCucumberUsage -- Time elapsed: 11.11 s <<< ERROR!
java.lang.RuntimeException: Expecting build failure, have got none!
	at org.apache.maven.surefire.its.fixture.MavenLauncher.executeGoal(MavenLauncher.java:250)
	at org.apache.maven.surefire.its.fixture.MavenLauncher.executeTest(MavenLauncher.java:212)
	at org.apache.maven.surefire.its.CucumberIT.simpleCucumberUsage(CucumberIT.java:52)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

@mirkoalicastro

Copy link
Copy Markdown
Contributor Author

Thanks @olamy. I guess I initially ran the IT with older version than 17. I fixed it and add a unit test for it.

@mirkoalicastro

Copy link
Copy Markdown
Contributor Author

@olamy , any chance you could check now that the pipeline is green?

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes incorrect test attribution when rerunFailingTestsCount is used with JUnit Platform @Suite, where tests from different classes could be merged under the Suite class name (leading to real failures being misclassified as flakes). The change updates RunListenerAdapter.findTopParent() to stop traversal at nested engine boundaries inside Suites so the reported source class remains the real test class (while still falling back to the Suite class for engines that don’t expose class-level sources, e.g., Cucumber).

Changes:

  • Update RunListenerAdapter.findTopParent() to stop at nested engine boundaries inside a Suite when a ClassSource is present.
  • Add unit coverage simulating Suite β†’ nested engine (Jupiter) and Suite β†’ nested engine (Cucumber-like, no ClassSource) hierarchies.
  • Update an integration test expectation to match the new XML report file naming/attribution behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java Adjusts top-parent detection to avoid attributing nested-engine tests to the enclosing Suite class when a real test class is available.
surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTest.java Adds unit tests covering Suite-with-nested-engine attribution for both Jupiter-style and Cucumber-style hierarchies.
surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1787JUnit45IT.java Updates the expected Surefire XML report filename/classname attribution for the JUnit 5 Suite integration scenario.

if (lastOpen >= 0) {
int colon = uniqueId.indexOf(':', lastOpen);
if (colon > lastOpen) {
return "engine".equals(uniqueId.substring(lastOpen + 1, colon));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything less brittle than relying on this?
@sormuras any idea how to identify a node being the engine?

@sormuras sormuras Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mh, there's no direct API like UniqueId::isEngine in https://docs.junit.org/6.1.2/api/org.junit.platform.engine/org/junit/platform/engine/UniqueId.html ... πŸ€”

@marcphilipp Any idea?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this help?

testIdentifier.getUniqueIdObject().getLastSegment().isEngine()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should do it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, that API was introduced in 6.1.1. You can check for "engine".equals(segment.getType()), though, in earlier versions.

@olamy olamy self-assigned this Aug 6, 2026
@olamy olamy added the bug Something isn't working label Aug 6, 2026
@olamy olamy added this to the 3.6.0-M2 milestone Aug 6, 2026
@olamy
olamy merged commit ce23cec into apache:master Aug 6, 2026
27 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants