Parallel tests in subprojects

We moved to JUnit 5 and want to make use of concurrent running tests. We are using sub projects, and some projects have tests which can be run concurrently (both on class and test level), while others cannot

Which is the best way to enable only some projects to run concurrent tests? I’ve played around with system properties, but I haven’t found the solution yet.

We found that we can disable parallel execution of tests on specific projects by setting maxParallelForks. It is project specific, in fact task specific, and won’t affect others:

test {
    maxParallelForks = 1; // Will not do parallel execution
}
1 Like

OK - I did try the opposite, by setting maxParallelForks = 1 in the root project, and maxParallelForks > 1 in those projects I wanted parallel execution, but I could not make it work. Will try some more then.

How are you enabling parallel execution in other projects?

We leave maxParallelForks as is or set it to more than 1. You may need to invoke Gradle with --parallel and --max-workers

See

1 Like

Gradle (we’re on 5.6.2) is set up with parallel execution through gradle.properties, and max workers defaults to # processors as I understand. You don’t activate concurrency through @Execution, or either properties file or system properties? My tests don’t seem to run in parallel unless I do something like this

tasks.test{
     // this runs in parallel
     useJunitPlatform()
     systemProperties['junit.jupiter.execution.parallel.enabled'] = true
     systemProperties['junit.jupiter.execution.parallel.mode.default'] = 'concurrent'
     systemProperties['junit.jupiter.execution.parallel.mode.default.classes'] = 'concurrent'
}

Config below runs test sequentially

tasks.test{
     useJunitPlatform()
     maxParallelForks = 24
}

Config below runs test in parallel even with maxParallelForks = 1

tasks.test{
     useJunitPlatform()
     systemProperties['junit.jupiter.execution.parallel.enabled'] = true
     systemProperties['junit.jupiter.execution.parallel.mode.default'] = 'concurrent'
     systemProperties['junit.jupiter.execution.parallel.mode.default.classes'] = 'concurrent'
     maxParallelForks = 1
}

You may need to set the forkEvery property

See Relationship between forkEvery, maxParallelFork and --parallel

1 Like

The overall goal here is to have have gradle build my project as fast as possible. The project has a lot of sub projects with a lot of tests. There are so many sub projects that I don’t want to define the test task in each. I either want to enable parallel execution in general, and disable parallelity in projects which fail (preferred solution), or the other way around.

So if I define the default test tasks as

maxParallelForks = 1
forkEvery = 1 // assuming this is what you suggest

What is the effect for all my tests that run with this config compared to just letting them run with sequentially? The effect of starting a new process vs reuse which I assume is the case for sequential execution?

I’m finding the test setup hard to understand, at least how these system properties I’m playing with affect the use of for instance maxParallelForks. Is my use of system properties the way to go, or am I doing it all wrong?

The Test task can launch multiple junit (or testng) processes in series or parallel. The properties on the Test task manage this behavior.

I’m unfamiliar with your system properties but I believe these will affect the junit process once it is launched by gradle (which could already be multiple/parallel)

Is my use of system properties the way to go

You can achieve parallel test execution without the jupiter specific system properties. I’d suggest that you either configure the parallelism in Gradle or via jupiter system properties, but not both (please note my earlier comment that I’m unfamiliar with the jupiter config)

There are so many sub projects that I don’t want to define the test task in each

Since Gradle scripts are groovy (or kotlin) you can configure multiple projects programmatically. Eg:

[':projectA', ':projectB'].each {
   project(it) {
      tasks.withType(Test) {
         maxParallelForks = 1
      } 
   } 
} 
1 Like

I agree, it felt messy from the start. Thank you for your input, I will try to make it work with gradle.