What does the `filter {}` block inside a `Test` task do, and how do `includeTestsMatching` and `excludeTestsMatching` work?
answer
- filter {} on Test task
- includeTestsMatching / excludeTestsMatching
- FQN + * wildcard
- OR-ed inclusions
- failOnNoMatchingTests default true
basics
~10 sThe filter {} block on a Test task selects which tests run by pattern. includeTestsMatching('*Foo*') keeps only matching tests; excludeTestsMatching drops matching ones. Patterns match fully-qualified class/method names with * wildcards.
solid answer
~30 sEvery `Test` task (like `test`) exposes a persistent `filter {}` block in the build script. `includeTestsMatching(pattern)` whitelists tests whose fully-qualified name matches; `excludeTestsMatching(pattern)` blacklists them. Patterns use `*` as a wildcard and dot-separate package, class and method (`com.acme.OrderTest.shouldPay`, `*IntegrationTest`, `*.slow*`). Multiple include patterns are OR-ed together. Unlike the transient `--tests` command-line option, `filter {}` is declared in the build and applies on every run, making it the right tool for permanent partitioning (e.g. excluding slow tests from the default `test` task). By default `failOnNoMatchingTests` is true, so a pattern matching nothing fails the build — useful to catch typos.
code
kotlin · 7 linestasks.test {
filter {
includeTestsMatching("com.acme.*Test")
excludeTestsMatching("*SlowTest")
isFailOnNoMatchingTests = true
}
}go deeper
Know that filter {} selects tests by name pattern with *, and the include/exclude method names.
Explain FQN matching, OR-ing of includes, exclude-wins precedence, and failOnNoMatchingTests.
Contrast persistent build-script filtering with transient --tests; know when to prefer tags over name patterns.
Frame name-filters as brittle coupling to naming conventions; advocate tag-based categorization as the governance-friendly partitioning strategy across many modules.
## What the filter block is Gradle's JVM test execution is driven by `Test` tasks (the built-in `test` task is one; you can register more). Each `Test` task carries a `TestFilter` accessed through the `filter {}` configuration block. The filter narrows the set of discovered tests **before** they execute, independent of the test engine (JUnit 4, JUnit Platform, TestNG). ## The two methods - `includeTestsMatching(String pattern)` — adds an **inclusion** pattern. If any inclusion pattern is present, only tests matching at least one of them run (inclusions are OR-ed). - `excludeTestsMatching(String pattern)` — adds an **exclusion** pattern. Any test matching it is dropped, even if it matched an inclusion. ## Pattern syntax Patterns are matched against the **fully-qualified name** in the form `package.Class.method`. The only wildcard is `*` (matches any sequence of characters, including dots). Examples: - `com.acme.OrderTest` — every method of that class - `com.acme.OrderTest.shouldChargeCard` — a single method - `*IntegrationTest` — every class whose simple/qualified name ends in `IntegrationTest` - `*.ui.*` — anything in a `ui` sub-package There is no `?` single-char wildcard and no regex; it is glob-like only. ## Persistent vs. transient `filter {}` is **declared in the build script**, so it applies on every invocation of that task — the natural place to permanently shape a task (e.g. an `integrationTest` task that only ever runs `*IT`). The command-line `--tests` option is a **one-off override** for a single run and lives in the sibling topic. ## failOnNoMatchingTests ```kotlin tasks.test { filter { includeTestsMatching("*FastTest") isFailOnNoMatchingTests = true // default } } ``` With the default `true`, a filter that selects zero tests fails the build, catching renamed-away or mistyped patterns. Set it to `false` when an empty result is legitimate (e.g. a task that may have nothing to run in some modules). ## How it relates to tags The `filter {}` block matches on **names**. To partition by semantic category (slow/fast/db) you typically use JUnit Platform `@Tag` plus `useJUnitPlatform { includeTags(...) }` — a complementary mechanism. Name-filtering and tag-filtering can be combined on the same task.
- If both an include and an exclude pattern match the same test, what happens?Exclusion wins — the test is dropped. Excludes are applied after includes.
- What wildcard characters does the pattern support?Only `*`. It is glob-like, not a regex; there is no `?` and no character classes.
saying these in an interview costs you the question
- Claiming the patterns are regular expressions (they are glob-like with only `*`).
- Saying `filter {}` only works with JUnit 5 — it is engine-agnostic and pre-dates the platform.
- Confusing `filter {}` with the `--tests` CLI flag as if they were the same persistent mechanism.