What capability does the java-test-fixtures plugin create, and how does a consumer depend on another project's test fixtures?
answer
- plugin: java-test-fixtures
- src/testFixtures/java source set
- capability group:name-test-fixtures
- consume: testFixtures(project(':x'))
- keeps test code off prod classpath
basics
~10 sThe java-test-fixtures plugin adds a testFixtures source set and publishes a variant with capability group:name-test-fixtures. Consumers depend on it via testImplementation(testFixtures(project(":mod"))).
solid answer
~30 s`java-test-fixtures` is a built-in feature variant. Applying it creates a `testFixtures` source set, `testFixturesApi`/`testFixturesImplementation` configurations, and outgoing variants carrying the capability `${group}:${name}-test-fixtures:${version}`. The fixtures are compiled into a separate jar (classifier `test-fixtures`) and `testFixturesApi` dependencies are exposed to consumers. Another project consumes them with the `testFixtures(...)` notation, which requests that capability: ```kotlin dependencies { testImplementation(testFixtures(project(":domain"))) // or external: testImplementation(testFixtures("com.example:domain:1.0")) } ``` This is the canonical real-world example of feature variants: shared test helpers are published as an opt-in capability so production consumers never accidentally pull test code, while test code can. It publishes via Gradle Module Metadata.
code
kotlin · 13 lines// Producer
plugins {
`java-library`
`java-test-fixtures`
}
dependencies {
testFixturesImplementation("org.assertj:assertj-core:3.25.0")
}
// Consumer project
dependencies {
testImplementation(testFixtures(project(":domain")))
}go deeper
Know the plugin name and that you consume fixtures with testFixtures(project(...)).
Explain the generated source set, the -test-fixtures capability, and that production code never gets fixtures.
Tie it back to feature variants generally and discuss publishing the fixtures variant in Module Metadata.
Use it as the canonical pattern for sharing test scaffolding across a multi-module codebase without polluting production classpaths.
## What the plugin does Apply it: ```kotlin plugins { `java-library` `java-test-fixtures` } ``` This is essentially `registerFeature("testFixtures")` with a dedicated source set, wired up for you. It creates: - a **`testFixtures` source set** → put shared test helpers in `src/testFixtures/java`; - dependency buckets `testFixturesApi`, `testFixturesImplementation`; - consumable variants `testFixturesApiElements`, `testFixturesRuntimeElements`; - the **capability** `${group}:${name}-test-fixtures:${version}`; - a jar with the `test-fixtures` classifier. The project's own tests automatically see the fixtures. ## Consuming fixtures The `testFixtures(...)` helper builds a dependency that **requires the test-fixtures capability**: ```kotlin dependencies { // internal project testImplementation(testFixtures(project(":domain"))) // external module testImplementation(testFixtures("com.example:domain:1.0")) } ``` Under the hood this is equivalent to declaring the dependency with `capabilities { requireCapability("com.example:domain-test-fixtures") }`. Without the `testFixtures(...)` wrapper you get the normal main variant, **not** the fixtures. ## Why it's a good capability example Test fixtures are the textbook feature variant: shared test utilities (fake builders, base test classes) that must be reusable across modules but must **never** leak into a production classpath. By gating them behind a capability: - a production `implementation(project(":domain"))` gets only main code; - a `testImplementation(testFixtures(project(":domain")))` gets the fixtures; - there's exactly one place the fixtures live, versioned with the module. ## Publishing When you `from(components["java"])` and publish, the test-fixtures variant is included in Gradle Module Metadata so external consumers can request it. POM-only consumers see it as a classified jar. ## Common pitfall Forgetting the `testFixtures(...)` wrapper — `testImplementation(project(":domain"))` resolves the main variant and the helper classes won't be found, leading to compile errors in tests.
- What is the exact capability coordinate for test fixtures of com.example:domain:2.0?`com.example:domain-test-fixtures:2.0` — base GAV with `-test-fixtures` appended to the artifact name.
- What happens if you write testImplementation(project(":domain")) without the testFixtures wrapper?You get the main variant only, not the fixtures. The fixture classes won't be on the test classpath and your tests won't compile against them.
saying these in an interview costs you the question
- Saying test fixtures are automatically on every consumer's classpath — they require the testFixtures(...) opt-in.
- Forgetting they're published as a separate classified jar / variant.