Search code examples
unit-testinggradlejunitbuild.gradlejunit5

How to use JUnit 5 with Gradle?


I am trying to use JUnit 5 with Gradle after I succeeded in running a JUnit 4 test.

Expected result: The JUnit 4 test gave a nice 'passed' in the output and an html report in build/reports/tests.

Actual result: The JUnit 5 test as below does not output anything besides (...) build successful, while I know the test is not actually run since there is no test log output passed/skipped/failed, and putting a fail in the test keeps the build successful.

Running gradle test --info yields Skipping task ':testClasses' as it has no actions. among a lot of I think mostly irrelevant output. Surprisingly, it also says Executing task ':test' and Generating HTML test report... Finished generating test html results and similar for the xml in build/test-results/test, while the xml is not generated, the html shows no tests run and no errors, and the test is indeed not run.

What I also think very interesting, is that gradle test --debug yields

[TestEventLogger] Gradle Test Run :test STARTED
[org.gradle.api.internal.tasks.testing.junit.JUnitDetector] test-class-
scan : failed to scan parent class java/lang/Object, could not find the class file
[TestEventLogger]
[TestEventLogger] Gradle Test Run :test PASSED

while my only test contains

fail("test fails");

which I think is very strange!

My build file is

apply plugin: 'java'

test {
    dependsOn 'cleanTest' // run tests every time

}

sourceSets {
    main {
        java {
            srcDirs 'src'
        }
    }
    test {
        java {
            srcDirs 'test'
        }
    }
}

repositories {
    mavenCentral()
}

dependencies {
    // when using this, it worked with a junit 4 test
//    testCompile 'junit:junit:4.10'
    // this should be needed for junit 5 (using M4 is required since IJ 2017.1.2
    testCompile("org.junit.jupiter:junit-jupiter-api:5.0.0-M4")
}

test {
    testLogging {
        events "passed", "skipped", "failed"
    }
}

My test is

package mypackage;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class HelloWorldTest {
    @Test
    public void testHelloWorld(){
        assertEquals(2, 1+1, "message");
    }
}

My folder structure is, using package mypackage,

java-template-project
--- src
    --- mypackage
        --- HelloWorld.java
--- test
    --- mypackage
        --- HelloWorldTest.java

and in IntelliJ 2017.1.3, which I am using, the module structure looks like this

java-template-project
--- java-template-project_main
    --- src/mypackage
        --- HelloWorld(.java)
--- java-template-project_test
    --- test/mypackage
        --- HelloWorldTest(.java)

because Gradle nowadays wants the source and tests in their own package.

What I tried

Obviously this is not the first question about this topic, all the relevant questions I found are


Solution

  • You need the engines for both JUnit versions, and you need to apply the JUnit platform gradle plugin. I do not see that in your gradle file. Here is a working gradle build executing both JUnit 4 and 5:

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath ("org.junit.platform:junit-platform-gradle-plugin:1.0.0-M4")
        }
    }
    
    apply plugin: 'org.junit.platform.gradle.plugin'
    ...
    
    dependencies {
    ...
        testCompile("junit:junit:4.12")
        testRuntime("org.junit.vintage:junit-vintage-engine:4.12.0-M4")
    
        testCompile("org.junit.jupiter:junit-jupiter-api:5.0.0-M4")
        testRuntime("org.junit.jupiter:junit-jupiter-engine:5.0.0-M4")
    
        // Enable use of the JUnitPlatform Runner within the IDE
        testCompile("org.junit.platform:junit-platform-runner:1.0.0-M4")
    }
    
    junitPlatform {
        details 'tree'
    }
    

    See the JUnit doc form more information on that.