Junit5: JUnit Jupiter @Nested tests do not run when selecting enclosing class with Surefire

Created on 26 Mar 2018  路  13Comments  路  Source: junit-team/junit5

Overview

Per Marc Philipp's request on Stack Overflow:

I'm trying to use JUnit Jupiter in my side project as a trial before migrating my main project. I'd like to use @Nested tests to make my test classes cleaner.

Everything is fine when I ran my test suite as a whole. However, as soon as I try running just a single test, @Nested ones are not executed.

mvn -Dtest=com.mycompany.test.MyTest surefire:test

Using JUnit 5.1.0, JUnit platform 1.1.0

<build>
<plugins>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <dependencies>
      <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-surefire-provider</artifactId>
        <version>${org.junit.platform.version}</version>
      </dependency>
      <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>${org.junit.version}</version>
      </dependency>
    </dependencies>
  </plugin>
</plugins>
</build>

Test class:

public class MyTest {

  @Test
  public void thisTestExecutes() { }

  @Nested
  public class NestedTests {
    @Test
    public void thisTestDoesnt() { }
  }
}

Related Issues

  • #1377
  • #1378
Maven Surefire Platform bug

Most helpful comment

Findings:

After adding a @Nested test class to FirstTest from the junit5-maven-consumer project and adding "no excludes" work-around discussed in #1377, we see that...

The following does not execute the nested test class.

./mvnw clean -Dtest=com.example.project.FirstTest test

However, the following does execute the nested test class. Note the trailing * after the fully qualified class name.

./mvnw clean -Dtest=com.example.project.FirstTest* test

After further analysis, I have determined that the above behavior is also experienced even if the "no excludes" work-around discussed in #1377 is not applied.

In summary, the "no excludes" work-around discussed in #1377 does not resolve _this_ issue, and I am therefore moving this to 5.3.

All 13 comments

This is an interesting use case - I don't believe it represents a bug in JUnit 5 or in Surefire - Surefire provides a generalized way to discover tests, filter them and then executes them individually. It adapts to each test engine via the Provider API.

When you run mvn test, Surefire delegates the discovery of the tests to JUnit 5, then filters them by using the complete class name (as you've provided) or by globbing each name for you. You should get the same behavior executing mvn -Dtest=MyTest surefire:test. Nested test classes are no different that other Java inner classes and so you end up with a class named MyTest$NestedTests on your classpath.

Surefire has recently added the ability to filter on method names to the test parameter, so you might expect you could run the inner classes tests with MyTest$NestedTests but when you do this, Surefire runs the outer class - it seems the filter specification doesn't provide a way to run tests in inner classes. This makes sense as I believe that JUnit 5 is the first Provider to support inner classes (I suspect tests in inner classes might run in JUnit 4 but they'd do so without the context of the outer class - note that I haven't tried this).

So, it appears that a feature request needs to be made to the Surefire project. This could go one of two ways:

  1. Implicitly include inner classes contained by tests selected by the filter
  2. Explicitly require users to list the inner classes they want to select but alter the filter to allow the user to supply inner class names.

While Surefire provides the filter, it's the Provider's responsibility to apply it.

This is what we currently do:

https://github.com/junit-team/junit5/blob/4c8c469332e962600ca5dab6165035ee6e9e1677/junit-platform-surefire-provider/src/main/java/org/junit/platform/surefire/provider/TestMethodFilter.java#L28-L55

I'm wondering whether we should add a special case when the test class is an inner class (i.e. it has an enclosing class and is not static), the TestListResolver does not have a method pattern and accepts any of the enclosing classes of the test class.

@marcphilipp I'd forgotten that the Provider actually does the filtering. Since Surefire is preprocessing the filters (at a minimum to do the globbing), do we know for certain that something like MyTest$NestedTests would be passed to the Provider? If not, I think the automatic inclusion of inner classes that you've described is the only option.

Would there ever be a need to execute a single test method within an inner (@Nested) class? - Perhaps a pseudo-filter something like MyTest$NestedTests#thisTestDoesnt. I also realized that I didn't test the use of a period as a outerclass/innerclass separator. MyTest.NestedTests might work (I can try this when I get back to my home computer tonight).

FYI: I reproduced the bug discussed in the above SO comment.

Non-private, static, nested test classes are also not executed via the JUnit Platform Maven Surefire provider when executing mvn test.

The OP for the aforementioned SO post will likely create a separate issue for that, but I wanted to make sure it's mentioned here as well, so that we don't forget it.

FYI: the solution to this issue _may_ be the same as for #1377.

Namely, Maven Surefire excludes all nested classes by default!

http://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#excludes

Tentatively slated for 5.2 GA in order to verify whether or not the _fix_ for #1377 covers this use case as well.

_in progress_: investigating

Findings:

After adding a @Nested test class to FirstTest from the junit5-maven-consumer project and adding "no excludes" work-around discussed in #1377, we see that...

The following does not execute the nested test class.

./mvnw clean -Dtest=com.example.project.FirstTest test

However, the following does execute the nested test class. Note the trailing * after the fully qualified class name.

./mvnw clean -Dtest=com.example.project.FirstTest* test

After further analysis, I have determined that the above behavior is also experienced even if the "no excludes" work-around discussed in #1377 is not applied.

In summary, the "no excludes" work-around discussed in #1377 does not resolve _this_ issue, and I am therefore moving this to 5.3.

@sormuras Sorry if I'm being dense, but I can't tell from the history. Was this fixed, or was it closed for another reason?

I'm in the process of moving Surefire-related issues over to https://issues.apache.org/jira/projects/SUREFIRE/issues

Thanks.

Was this page helpful?
0 / 5 - 0 ratings