Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run JUnit4 tests parallel using gradle

I would like to run tests in parallel using Gradle. My experiments show me that Gradle run tests in parallel on class level. I need them to be executed on method level.

Given two test classes like this:

public class OneTest {
    @Test
    public void should_sleep_4_seconds() throws Exception {
        System.out.println("Start 4 seconds");
        Thread.sleep(4000);
        System.out.println("Done 4 seconds");
    }
}
public class ManyTest {

    @Test
    public void should_sleep_1_seconds() throws Exception {
        System.out.println("Start 1 seconds");
        Thread.sleep(1000);
        System.out.println("Done 1 seconds");
    }

    @Test
    public void should_sleep_2_seconds() throws Exception {
        System.out.println("Start 2 seconds");
        Thread.sleep(2000);
        System.out.println("Done 2 seconds");
    }
}

And a build script like this:

plugins {
    id 'java'
}

sourceCompatibility = '1.8'
targetCompatibility = '1.8'

dependencies {
    testCompile 'junit:junit:4.12'
}

test {
    testLogging.showStandardStreams = true
    maxParallelForks = 3
}

repositories {
    mavenCentral()
}

I can get this result:

./gradlew clean test

> Task :test

se.thinkcode.ManyTest > should_sleep_2_seconds STANDARD_OUT
    Start 2 seconds

se.thinkcode.OneTest > should_sleep_4_seconds STANDARD_OUT
    Start 4 seconds

se.thinkcode.ManyTest > should_sleep_2_seconds STANDARD_OUT
    Done 2 seconds

se.thinkcode.ManyTest > should_sleep_1_seconds STANDARD_OUT
    Start 1 seconds
    Done 1 seconds

se.thinkcode.OneTest > should_sleep_4_seconds STANDARD_OUT
    Done 4 seconds

BUILD SUCCESSFUL in 5s
3 actionable tasks: 3 executed

This tells me that there is parallelism but that it is only on class level, not method level.

Is there any native way to make Gradle do the execution in one thread per test method?

like image 798
Thomas Sundberg Avatar asked Oct 28 '22 20:10

Thomas Sundberg


2 Answers

It is not possible to use Gradles JUnit 4 runner to run tests in parallel for anything but classes.

I can't confirm this works but you may want to try the JUnit Platform + JUnit Vintage from JUnit 5. Have a look at the JUnit 5 starters to see how to set that up.

dependencies {
    def junit4Version = '4.12'
    def junit5Version = '5.3.2'
    implementation(enforcedPlatform("org.junit:junit-bom:${junit5Version}")) {
        because 'enforce matching Platform, Jupiter, and Vintage versions'
    }

    // JUnit Jupiter
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testImplementation('org.junit.jupiter:junit-jupiter-params')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine') {
        because 'allows JUnit 5 (read Jupiter) tests to run'
    }

    // JUnit Vintage
    testImplementation("junit:junit:${junit4Version}")
    testRuntimeOnly('org.junit.vintage:junit-vintage-engine') {
        because 'allows JUnit 3 and JUnit 4 tests to run'
    }
}

You can then add junit.jupiter.execution.parallel.enabled=true to junit-platform.properties to enable parallel execution. See the JUnit 5 User Guide - Parallel Execution.

like image 109
M.P. Korstanje Avatar answered Nov 02 '22 23:11

M.P. Korstanje


It's not possible (yet ?) in Gradle. The finest level is classes where Maven Surefire plugin can go down to methods level

like image 27
ToYonos Avatar answered Nov 02 '22 23:11

ToYonos