Capture and verify STDOUT and STDERR in tests
In this example the function that we are testing also prints to the STDOUT and STDERR. We would like to extend our tests to verify that the output is as expected on both channels.
#![allow(unused)] fn main() { pub fn add(left: u64, right: u64) -> u64 { println!("Left: {left}"); eprintln!("Right: {right}"); left + right } #[cfg(test)] mod tests; }
We'll use the gag crate for this:
[package]
name = "test-output"
version = "0.1.0"
edition = "2024"
[dependencies]
[dev-dependencies]
gag = "1.0.0"
Unfortunatelly for that crate to be able to the magic while in the tests we also need to pass the --nocapture
flag to the tests. We can do it manually cargo run test --nocapture or we can setup an alias in the .cargo/config.toml file:
[alias]
t = "test -- --nocapture"
Then we can run cargo t.
The actual test looks like this:
#![allow(unused)] fn main() { use super::*; use gag::BufferRedirect; use std::io::Read; #[test] fn it_works() { let mut stdout_buf = BufferRedirect::stdout().unwrap(); let mut stderr_buf = BufferRedirect::stderr().unwrap(); let result = add(2, 3); assert_eq!(result, 5); let mut stdout_output = String::new(); stdout_buf.read_to_string(&mut stdout_output).unwrap(); drop(stdout_buf); let mut stderr_output = String::new(); stderr_buf.read_to_string(&mut stderr_output).unwrap(); drop(stderr_buf); assert_eq!(stdout_output, "Left: 2\n"); assert_eq!(stderr_output, "Right: 3\n"); } }
It has a lot of code, but eventually it collects the STDOUT and STDERR and we can compare them to some expected value.