Show standard output and standard error in tests in Rust

testing STDOUT STDERR --show-output

Sometimes our code prints to the screen, either to the standard output channel or the standard error channel. There are cases when we might want to verify the content of what was printed in other case we just would like to see.

By default when we run cargo test, it will capture and hide both channels. Using the --show-output we can convince cargo to print the captured output.

In this example we'll see this working both inline tests that are usually used for unit-testing and external tests that, in this case, run our code as an external program as we can also see in the article on how to test command line application.

Code with inline tests

examples/show-output-in-tests/src/main.rs

fn main() {
    answer();
}

fn answer() -> u32 {
    println!("STDOUT in code");
    eprintln!("STDERR in code");
    42
}

#[test]
fn test_function() {
    println!("STDOUT In test_function");
    eprintln!("STDERR In test_function");

    assert_eq!(answer(), 42);
}

External tests

Running the program as a command line application we would probably check that the text printed to the STDOUT and STDERR by the program is what we expect. Still we have some text printed by the test that we would like to see.

examples/show-output-in-tests/tests/tests.rs

use std::{
    os::unix::process::ExitStatusExt,
    process::{Command, ExitStatus},
};

#[test]
fn test_cli() {
    println!("STDOUT In test_cli");
    eprintln!("STDERR In test_cli");

    let result = Command::new("cargo")
        .args(["run", "-q"])
        .output()
        .expect("command failed to start");

    assert_eq!(
        std::str::from_utf8(&result.stdout).unwrap(),
        "STDOUT in code\n"
    );
    assert_eq!(
        std::str::from_utf8(&result.stderr).unwrap(),
        "STDERR in code\n"
    );
    assert_eq!(result.status, ExitStatus::from_raw(0));
}

Regular test output

$ cargo test -q

running 1 test
.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


running 1 test
.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s

The upper part shows the inline test

Running the tests and showing the output

$ cargo test -q -- --show-output

running 1 test
.
successes:

---- test_function stdout ----
STDOUT In test_function
STDERR In test_function
STDOUT in code
STDERR in code


successes:
    test_function

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


running 1 test
.
successes:

---- test_cli stdout ----
STDOUT In test_cli
STDERR In test_cli


successes:
    test_cli

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s

Note

The -q is an option of cargo, but --show-outputis a parameter of the test runner. So we need the extra--` in order to pass this argument to the actual test runner.

Related Pages

Testing in Rust
Rocket - access custom configuration in the routes

Author

Gabor Szabo (szabgab)

Gabor Szabo, the author of the Rust Maven web site maintains several Open source projects in Rust and while he still feels he has tons of new things to learn about Rust he already offers training courses in Rust and still teaches Python, Perl, git, GitHub, GitLab, CI, and testing.

Gabor Szabo