Test Output and Diagnostics
By default, Rust's test harness captures standard output and standard error produced by println!, eprintln!, and dbg! during each test:
- If a test passes, its captured output is silently discarded so the terminal displays only a clean
test name ... okline. - If a test fails, the harness prints the entire captured
stdout/stderrbuffer for that test above the panic message to aid debugging.
Test Execution under `cargo test`:
println!("step 1") ---> [ Thread-Local Capture Buffer ]
|
+--------------------------+--------------------------+
| |
Test PASSES Test FAILS
Buffer discarded; Buffer dumped to terminal
prints only: `test foo ... ok` under `---- foo stdout ----`
Controlling Output Capture via Test Harness Flags
To pass flags to the compiled test binary itself (rather than to cargo), place them after -- in the cargo test command:
| Command | Behavior |
|---|---|
cargo test |
Captures stdout/stderr; prints output only for failing tests. |
cargo test -- --show-output |
Captures output during execution (preventing interleaved lines across threads), then prints captured output for both passing and failing tests at the end. |
cargo test -- --nocapture |
Disables output capturing completely; println! writes directly to the terminal in real time (output from parallel tests may interleave). |
pub fn compute_checksum(bytes: &[u8]) -> u32 {
let mut sum = 0u32;
for (i, &b) in bytes.iter().enumerate() {
sum = sum.wrapping_add((b as u32) * (i as u32 + 1));
}
sum
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn checksum_logs_intermediate_trace() {
let input = b"rust";
println!("Computing checksum for {:?}", std::str::from_utf8(input));
let result = compute_checksum(input);
println!("Computed checksum = {result}");
assert_eq!(result, 114 * 1 + 117 * 2 + 115 * 3 + 116 * 4);
}
}
fn main() {
println!("Checksum of 'rust': {}", compute_checksum(b"rust"));
}
Checksum of 'rust': 1157
Running cargo test -- --show-output displays the ---- stdout ---- section even though the test passed:
running 1 test
test tests::checksum_logs_intermediate_trace ... ok
successes:
---- tests::checksum_logs_intermediate_trace stdout ----
Computing checksum for Ok("rust")
Computed checksum = 1157
successes:
tests::checksum_logs_intermediate_trace
test result: ok. 1 passed; 0 failed; 0 filtered out; finished in 0.00s
Enabling Stack Backtraces on Test Failure (RUST_BACKTRACE)
When a test panics deep inside a call stack, set the RUST_BACKTRACE environment variable to see the exact sequence of stack frames leading to the failure:
RUST_BACKTRACE=1 cargo test: Prints a concise stack trace filtering out Rust runtime setup frames.RUST_BACKTRACE=full cargo test: Prints every frame including memory addresses and standard library internals.
Why Background Threads May Bypass Capture
The test harness captures println! and eprintln! by installing a thread-local output buffer on the test thread. If your test spawns raw OS threads (std::thread::spawn) or child processes (std::process::Command with Stdio::inherit()), output written directly to file descriptors 1 (stdout) or 2 (stderr) may bypass the capture buffer unless --nocapture is used.