How do you configure `testLogging` so the console shows passed, skipped, and failed test events with full stack traces?
answer
- testLogging { } block
- events: passed/skipped/failed
- exceptionFormat = FULL
- default logs only FAILED + SHORT
- showCauses / showStackTraces
basics
~10 sInside the test task use a testLogging { } block: set events("passed", "skipped", "failed") to print each event, and exceptionFormat = TestExceptionFormat.FULL to show complete stack traces instead of truncated ones.
solid answer
~40 sGradle's `Test` task exposes a `testLogging` container (`TestLoggingContainer`). The key knobs: `events` selects which `TestLogEvent`s appear (PASSED, SKIPPED, FAILED, STANDARD_OUT, STANDARD_ERROR, STARTED); `exceptionFormat` (`TestExceptionFormat.SHORT` default or `FULL`) controls how much of a failure's stack trace prints; `showStackTraces`, `showCauses`, `showExceptions`, and `stackTraceFilters` refine the trace; `minGranularity`/`maxGranularity` choose whether you log at the test-method or suite level. By default only failed tests print, with a short exception, so CI logs often look empty for failures. Setting `events('passed','skipped','failed')` plus `exceptionFormat = FULL` gives a readable, debuggable console. You typically also configure the `lifecycle` log level (the default) or a per-level block. Note logging is purely about console output — it doesn't change pass/fail or which tests run.
code
kotlin · 10 linesimport org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
tasks.withType<Test>().configureEach {
testLogging {
events(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED)
exceptionFormat = TestExceptionFormat.FULL
showCauses = true
}
}go deeper
Know the testLogging { events(...) } block exists and that exceptionFormat = FULL gives full stack traces.
List the common events and exception options, explain the SHORT-default surprise, and that logging is purely cosmetic/observability.
Cover per-log-level configuration, granularity, standard-stream capture trade-offs with parallel forks, and applying config across all Test tasks with configureEach.
Standardize a convention plugin that sets sane testLogging defaults org-wide for readable CI logs, balancing verbosity against log volume costs.
## The `testLogging` container Every `Test` task has a `testLogging` property of type `TestLoggingContainer`. It actually holds settings *per log level* (`debug`, `info`, `lifecycle`, `warn`, `quiet`, `error`), but configuring the block directly applies to the default `lifecycle` level — the one you see in a normal `./gradlew test`. ## Events `events` takes one or more `TestLogEvent` values: - `STARTED`, `PASSED`, `SKIPPED`, `FAILED` - `STANDARD_OUT`, `STANDARD_ERROR` (capture what tests print to stdout/stderr) By default the lifecycle level logs only `FAILED`. Adding `PASSED` and `SKIPPED` gives a per-test summary line. ## Exception formatting When a test fails, how much of the throwable prints is controlled by: - `exceptionFormat`: `TestExceptionFormat.SHORT` (default — a one-liner) or `FULL` (the entire stack trace). - `showExceptions` (default true), `showCauses` (print `Caused by:` chains), `showStackTraces`. - `stackTraceFilters`: e.g. `GROOVY`, `ENTRY_POINT`, `TRUNCATE` to trim noise. For real debugging you almost always want `exceptionFormat = TestExceptionFormat.FULL`. ## Granularity `minGranularity` / `maxGranularity` choose the level in the test tree (suite vs. class vs. method) at which events are emitted. `maxGranularity = -1` (default) logs at the leaf (method) level. ## Putting it together ```kotlin import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent tasks.withType<Test>().configureEach { testLogging { events( TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED, ) exceptionFormat = TestExceptionFormat.FULL showCauses = true showStackTraces = true showStandardStreams = false } } ``` In Groovy DSL the events can be passed as strings: `events 'passed', 'skipped', 'failed'` and `exceptionFormat 'full'`. ## Scope reminder `testLogging` only shapes the **console output**. It has zero effect on which tests run, the build outcome (`ignoreFailures`), or early termination (`failFast`). It's purely observability.
- Why do failing tests sometimes show almost no detail in CI by default?Because the default `exceptionFormat` is `SHORT` (a truncated stack trace) and only the `FAILED` event is logged. Setting `exceptionFormat = TestExceptionFormat.FULL` and optionally `showCauses`/`showStackTraces` restores the full trace.
- How do you see what your tests print to stdout/stderr in the console?Add `STANDARD_OUT` and `STANDARD_ERROR` to `events`, or set `showStandardStreams = true`. Be aware this can be very noisy with parallel forks.
- Does configuring `testLogging` for the lifecycle level also apply when running with `--info`?No — each log level has its own `testLogging` config. Configuring the block applies to lifecycle; `--info` uses the `info` level's settings unless you configure `testLogging.info { ... }` too.
saying these in an interview costs you the question
- Thinking `testLogging` changes the build result or which tests run — it only affects console output.
- Assuming full stack traces print by default; the default is SHORT.
- Confusing the lifecycle-level config with per-level (`info`, `debug`) blocks.