7
votes

I have two types of tests in my code, ending with UnitTest and IntegrationTest. Of course there are some legacy JUnit 4 tests and new ones supposed to be written with JUnit 5.

What I want:

UnitTestSuite and IntegrationTestSuit classes that could be run from IDE (IntelliJ IDEA) and each of them have filters by the class name ending of tests. Also I want two different gradle tasks each to run their own set of tests (based on suits ideally, or also on the class names at least).

What I've tried:

This test suite works well from IDE, and as I understand it should run both JUnit 4 and JUnit 5 tests. However, it seems that this approach is more like a workaround and not actual suites support.

@RunWith(JUnitPlatform.class)
@IncludeClassNamePatterns({ "^.*UnitTest$" })
public class UnitTestSuite {
}

Also I created this Gradle task, but it doesn't run any tests saying to me:

WARNING: Ignoring test class using JUnitPlatform runner

test { Test t ->

    useJUnitPlatform()

    include "UnitTestSuite.class"
}

So is there a solution to run both JUnit 4 and JUnit 5 tests, filtered by name (gathered into suits) from the IDE and from the Gradle task?

2

2 Answers

4
votes

In Gradle you can configure multiple test tasks, one for JUnit 4 and one for JUnit 5.

I did exactly that in the Spring Framework build. See the testJUnitJupiter and test tasks in spring-test.gradle.

task testJUnitJupiter(type: Test) {
    description = "Runs JUnit Jupiter tests."
    useJUnitPlatform {
        includeEngines "junit-jupiter"
        excludeTags "failing-test-case"
    }
    filter {
        includeTestsMatching "org.springframework.test.context.junit.jupiter.*"
    }
    reports.junitXml.destination = file("$buildDir/test-results")
    // Java Util Logging for the JUnit Platform.
    // systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
}

test {
    description = "Runs JUnit 4 tests."
    dependsOn testJUnitJupiter, testNG
    useJUnit()
    scanForTestClasses = false
    include(["**/*Tests.class", "**/*Test.class"])
    exclude(["**/testng/**/*.*", "**/jupiter/**/*.*"])
    reports.junitXml.destination = file("$buildDir/test-results")
}

You can of course name them and configure them however you want.

2
votes

Alternative option with some caveats is to run JUnit 4 (and even 3) tests using JUnit 5. To do so you will need vintage engine on your runtime classpath, like so:

def junit5Version = "5.7.0"
dependencies {
    // other deps
    testImplementation "org.junit.jupiter:junit-jupiter:${junit5Version}"
    testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit5Version}"
}

This also works from IntelliJ IDEA.

Source and further instructions on how to make some other JUnit 4 features work with JUnit 5 are here: https://junit.org/junit5/docs/current/user-guide/#migrating-from-junit4-running