You want unit tests to run before a custom integration suite during `check`, but running `gradle integrationTest` alone should NOT trigger unit tests. How do you express this, and what's the trap with `dependsOn`?
answer
- ordering ≠ dependency
- shouldRunAfter(test) on integration target
- dependsOn(test) wrongly forces unit suite
- check.dependsOn for execution only
- shouldRunAfter is best-effort vs mustRunAfter
basics
~10 sUse shouldRunAfter(test) on the integration target's testTask — a soft ordering. Don't use dependsOn(test), which would force unit tests to run every time you run integration tests.
solid answer
~40 sConfigure the integration suite's target with `testTask.configure { shouldRunAfter(test) }`. `shouldRunAfter` is an **ordering rule, not a dependency**: when both `test` and `integrationTest` are in the same execution graph (e.g. under `check`), Gradle runs unit tests first to fail fast; but asking only for `integrationTest` won't drag `test` in. The trap is reaching for `dependsOn(test)` to get ordering — that's a hard edge, so `gradle integrationTest` would also execute the entire unit suite, defeating the point of running them independently. Keep `check` wired with `dependsOn(integrationTest)` for *execution*, and use `shouldRunAfter` purely for *order*. Note `shouldRunAfter` is best-effort: Gradle may ignore it to avoid cycles or with certain parallel scheduling, whereas `mustRunAfter` is a stronger (still non-dependency) ordering constraint.
code
kotlin · 11 linesval integrationTest by testing.suites.registering(JvmTestSuite::class) {
targets {
all {
testTask.configure {
shouldRunAfter(test) // order only, no forcing
}
}
}
}
tasks.named("check") { dependsOn(integrationTest) }go deeper
Know that ordering and 'must run' are different; shouldRunAfter orders without forcing.
Apply shouldRunAfter(test) and avoid dependsOn(test) for ordering.
Explain the execution-vs-ordering distinction and mustRunAfter vs shouldRunAfter tradeoffs.
Codify fail-fast ordering as a build convention and reason about parallel-scheduling edge cases.
## Two orthogonal axes: execution vs. ordering Gradle separates *whether* a task runs (dependencies) from *when relative to others* (ordering rules): - **Dependencies** — `dependsOn`. Hard: pulling task A pulls task B, and B runs before A. - **Ordering rules** — `mustRunAfter` / `shouldRunAfter`. They only constrain order *if both tasks are already scheduled*; they never cause a task to be executed. ## The requirement "Unit before integration in `check`, but `integrationTest` alone stays cheap." That's exactly an ordering rule, not a dependency: ```kotlin testing { suites { val integrationTest by registering(JvmTestSuite::class) { targets { all { testTask.configure { shouldRunAfter(test) } } } } } } tasks.named("check") { dependsOn(integrationTest) } ``` Under `gradle check`, both `test` and `integrationTest` are scheduled, so `shouldRunAfter` orders them (fail fast on fast unit tests). Under `gradle integrationTest`, `test` is not scheduled, so nothing forces it. ## The `dependsOn` trap If instead you wrote `testTask.configure { dependsOn(test) }`, then `gradle integrationTest` would also run the full unit suite — wasteful and surprising. Use `dependsOn` only on `check` (to guarantee the suite executes in the lifecycle), never to express ordering between the two test runs. ## `shouldRunAfter` vs. `mustRunAfter` - `mustRunAfter(test)` — a hard ordering constraint (still not a dependency); Gradle won't reorder it. - `shouldRunAfter(test)` — best-effort; Gradle may drop it to break a cycle or in some parallel scenarios. For test ordering, `shouldRunAfter` is the conventional choice because it expresses a preference without risking cycle-related failures. ## Summary table | Goal | Use | |------|-----| | Make `check` run the suite | `check.dependsOn(integrationTest)` | | Run unit before integration when both run | `integrationTest.shouldRunAfter(test)` | | NEVER | `integrationTest.dependsOn(test)` |
- What's the difference between `mustRunAfter` and `shouldRunAfter`?Both are ordering rules, not dependencies. `mustRunAfter` is hard ordering; `shouldRunAfter` is best-effort and may be dropped to avoid cycles or under parallelism.
- Will `shouldRunAfter(test)` cause `gradle integrationTest` to run unit tests?No. Ordering rules only take effect when both tasks are already in the graph; running integration alone won't schedule `test`.
saying these in an interview costs you the question
- Using `dependsOn(test)` to get ordering — it forces unit tests on every integration run.
- Believing `shouldRunAfter` guarantees execution of the referenced task.
- Treating `shouldRunAfter` as a hard guarantee under all conditions.