Skip to content

[SUREFIRE-3465] Match includes/excludes the way the scanner does - #3466

Merged
olamy merged 2 commits into
apache:masterfrom
orion0616:fix/junit-platform-includes-filter
Sep 10, 2026
Merged

olamy merged 2 commits into
apache:masterfrom
orion0616:fix/junit-platform-includes-filter

Conversation

@orion0616

@orion0616 orion0616 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Since 3.6.0-M1 the JUnit Platform provider re-applies <includes>/<excludes> (and -Dtest) as a class name filter, but matched the scanner style patterns against the dot separated class name. An include with a package directory and **/ such as com/example/it/**/*IT.java, or a %regex[...] include, never matched, so the classes the plugin had already scanned were dropped again inside the fork and the build stayed green with Tests run: 0.

This change asks the same TestListResolver the plugin builds for its directory scanner, about the class file path (pkg/Name.class), so the provider can no longer reject a class the scanner selected, and the hand-written matching helpers go away. As a consequence %regex[...] is evaluated against the .class path as documented, Ant style and regex includes are alternatives of one filter instead of two filters that both had to match, -Dtest=!Class#method excludes only that method, and the default exclude **/*$* takes effect in the provider (it does not affect @Nested classes, which Jupiter never passes through a ClassNameFilter). The enclosing classes of scanned nested classes stay included as before (#3446), now for excludes as well as for includes.

The new IT covers a package directory include with **/, a **/dir/**/ include, a %regex[...] include and a package directory exclude; three of the four fail on master. Unit tests cover the pattern shapes the provider receives from the plugin, including the -Dtest forms, ! negation, includes combined with excludes and the enclosing class of a scanned nested class.

Fixes #3465

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).

Validation performed with JDK 17:

  • mvn -nsu -Dmaven.build.cache.enabled=false clean install (17-module reactor, 1481 unit tests; Spotless, Checkstyle, RAT and animal-sniffer pass)
  • mvn -Prun-its -pl surefire-its -Dit.test=Surefire3465IT clean verify (fails on master, passes with this change)
  • mvn -nsu -Dmaven.build.cache.enabled=false -Prun-its clean install (17-module reactor; 780 integration tests, 0 failures, 0 errors)

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.

An <includes> entry with a package directory prefix and `**/`, such as
issue3465/inner/**/*Test.java, or a %regex[...] include, does not run
the matching tests with the JUnit Platform provider, although the very
same configuration runs them with 3.5.6. The build stays green because
the tests are silently not executed.

Refs apache#3465
The provider re-applies <includes>/<excludes> (and -Dtest) as a class
name filter, so that classes an engine discovers on its own are filtered
the same way as the ones the plugin has scanned. That filter matched the
patterns against the dot separated class name, while the patterns
address the class file path. Patterns such as com/example/it/**/*IT.java
therefore never matched, the classes the plugin had selected were
dropped again inside the fork, and the build stayed green with
Tests run: 0.

The filter now delegates to the very same TestListResolver the plugin
builds from <includes> and <excludes> for its directory scanner, and
asks it about the class file path (pkg/Name.class). As a consequence
%regex[...] patterns are evaluated against the .class path as the
documentation describes them, instead of against the class name. Ant
style and regex patterns are also alternatives of one filter now, rather
than two filters that had to match both, and -Dtest=!Class#method
excludes only that method instead of the whole class.

The enclosing classes of the scanned classes stay included
unconditionally, now for excludes as well as for includes. Once the
scanner has decided that a nested class is to be run, rejecting its
enclosing class would contradict that decision and the nested class
would not be discovered at all (apache#3446).

This also makes the default exclude **/*$* effective in the provider,
where it previously never matched anything. Jupiter applies a
ClassNameFilter to the classes it resolves from a ClassSelector, never
to @nested ones, so nested tests keep being discovered through their
enclosing class.

Adds unit tests for the pattern shapes the provider receives from the
plugin.

Fixes apache#3465
@olamy

olamy commented Sep 9, 2026

Copy link
Copy Markdown
Member

sadly GHA are totally stucked :(

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.

3.6.0 regression: <includes> pattern with a package directory (e.g. com/example/it/**/*IT.java) runs zero tests

2 participants