What does the `maxParallelForks` property on Gradle's `Test` task do, and how do you set it?
answer
- concurrent forked test JVMs per Test task
- default = 1 (sequential)
- distributes test CLASSES, not methods
- half-cores heuristic
- not org.gradle.parallel
basics
~10 smaxParallelForks sets how many test JVM processes Gradle runs at once for a single Test task. Set it in the test task config, e.g. tasks.test { maxParallelForks = 4 }. Default is 1.
solid answer
~40 sEach `Test` task runs its test classes in forked JVM processes. By default Gradle uses a single fork, so all test classes run sequentially in one JVM. `maxParallelForks` raises the number of test JVMs Gradle may run concurrently for that task — Gradle distributes test classes across those forks, giving real speedup for CPU-bound or moderately I/O-bound suites. ```kotlin tasks.withType<Test>().configureEach { maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1) } ``` Key caveats: parallelism is **within** one Test task; tests in different classes can now run truly concurrently, so shared mutable state (static fields, fixed ports, shared DB schemas, temp files) becomes a hazard. It's distinct from `org.gradle.parallel` (which parallelises *projects/tasks*) and from JUnit 5's in-JVM parallelism. A common heuristic is half the available processors.
code
kotlin · 4 linestasks.withType<Test>().configureEach {
// run up to N test JVMs in parallel for this task
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1)
}go deeper
Know it sets the number of concurrent test JVMs and defaults to 1; be able to set it and mention the half-cores heuristic.
Explain class-level granularity, the difference from org.gradle.parallel and --max-workers, and the shared-state hazards parallelism exposes.
Discuss tuning trade-offs (memory/GC vs throughput), isolating flaky shared-state suites, and combining with engine-level parallelism.
Frame fork tuning as part of CI capacity planning — agent core/memory budgets, reproducibility, and standardising the heuristic across many modules.
## What forking means When Gradle's `Test` task runs, it does not execute your tests inside the Gradle daemon. It launches separate **forked JVM processes** ("test workers") and feeds test classes to them over a socket. This isolation keeps test-polluted classloaders and static state out of the build process. By default a `Test` task uses exactly **one** fork, so even though your machine has many cores, the test classes run one after another in a single JVM. ## maxParallelForks `maxParallelForks` is an `int` property on the `Test` task that caps how many of those forked JVMs may run **at the same time** for that one task. Gradle then hands out test *classes* to whichever fork is free, so different test classes execute truly in parallel across OS processes. ```kotlin tasks.withType<Test>().configureEach { maxParallelForks = 4 } ``` A portable, machine-aware setting derives it from the CPU count: ```kotlin maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1) ``` ## Granularity is the class Gradle's distribution unit is the **test class**, not the test method. A single class with 500 slow methods still runs in one fork; parallelism only helps when you have many classes. (Method-level parallelism is a separate concern handled inside the engine, e.g. JUnit 5's `junit.jupiter.execution.parallel.enabled`.) ## What it is NOT - It is **not** `org.gradle.parallel=true` — that flag parallelises *tasks across projects*, letting `:moduleA:test` and `:moduleB:test` run together. `maxParallelForks` parallelises *within one* Test task. - It is **not** the same as `--max-workers`, the global cap on Gradle worker processes. `maxParallelForks` is bounded by `--max-workers`: if the global cap is lower, you won't get all the forks you asked for. - It is **not** JUnit/TestNG in-JVM parallelism. ## Hazards introduced by parallelism Running classes concurrently surfaces hidden coupling: shared static singletons, hard-coded ports, a single shared database schema, fixed temp-file paths, or order dependence between classes. Fix by making each fork self-contained (random ports, per-fork DB schema, `@TempDir`), or isolate the offenders into their own sequential Test task. ## Picking a value There's no universally correct number. Half the cores is a safe start because test JVMs also consume memory and may themselves spawn threads. Profile: too few forks underuses the machine; too many causes memory pressure, GC thrash, and context-switching that can make the suite *slower*.
- Does maxParallelForks parallelise individual test methods?No. Gradle's distribution granularity is the test class. A single class runs entirely in one fork; method-level parallelism is the engine's job (e.g. JUnit 5's parallel execution config).
- How does maxParallelForks relate to org.gradle.parallel?They're orthogonal. org.gradle.parallel runs *tasks across projects* concurrently; maxParallelForks runs multiple test JVMs *within a single Test task*. You can use both together.
saying these in an interview costs you the question
- Claiming it parallelises test methods rather than test classes.
- Confusing it with org.gradle.parallel or --max-workers.
- Assuming higher is always faster, ignoring memory/GC overhead.