Reputation: 16402
I've implemented the following method and unit test:
use std::fs::File;
use std::path::Path;
use std::io::prelude::*;
fn read_file(path: &Path) {
let mut file = File::open(path).unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
println!("{contents}");
}
#[test]
fn test_read_file() {
let path = &Path::new("/etc/hosts");
println!("{path:?}");
read_file(path);
}
I run the unit test this way:
rustc --test app.rs; ./app
I could also run this with
cargo test
I get a message back saying the test passed but the println!
is never displayed on screen. Why not?
Upvotes: 657
Views: 221091
Reputation: 6641
In case you want to run the test displaying the printed output everytime the file changes:
cargo watch -x "test -- --nocapture"
Upvotes: 5
Reputation: 1025
Preface: This answer reflects a change in Rust 1.41 ("You can now pass --show-output
argument to test binaries to print the output of successful tests." per the CHANGELOG)
As mentioned by L. F., --show-output
is the way to go.
$ cargo test -- --show-output
Other display flags are mentioned in the documentation of cargo test in display-options.
Upvotes: 85
Reputation: 1809
Note that the modern solution (cargo test -- --show-output
) doesn't work in doctests defined in a Markdown code-fence in the docstring of your functions. Only println!
(etc.) statements done in a concrete #[test]
block will be respected.
Upvotes: 5
Reputation: 141
Why? I don't know, but there is a small hack eprintln!("will print in {}", "tests")
Upvotes: 1
Reputation: 127711
This happens because Rust test programs hide the stdout of successful tests in order for the test output to be tidy. You can disable this behavior by passing the --nocapture
option to the test binary or to cargo test
(but, in this case after --
– see below):
#[test]
fn test() {
println!("Hidden output")
}
Invoking tests:
% rustc --test main.rs; ./main
running 1 test
test test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
% ./main --nocapture
running 1 test
Hidden output
test test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
% cargo test -- --nocapture
running 1 test
Hidden output
test test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
If tests fail, however, their stdout will be printed regardless if this option is present or not.
Upvotes: 752
Reputation: 793
To include print outs with println!()
and keep colors for the test results, use the color
and nocapture
flags in cargo test
.
$ cargo test -- --color always --nocapture
(cargo version: 0.13.0 nightly)
Upvotes: 29
Reputation: 14950
TL;DR
$ cargo test -- --nocapture
With the following code:
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PieceShape {
King, Queen, Rook, Bishop, Knight, Pawn
}
fn main() {
println!("Hello, world!");
}
#[test]
fn demo_debug_format() {
let q = PieceShape::Queen;
let p = PieceShape::Pawn;
let k = PieceShape::King;
println!("q={:?} p={:?} k={:?}", q, p, k);
}
Then run the following:
$ cargo test -- --nocapture
And you should see
Running target/debug/chess-5d475d8baa0176e4
running 1 test
q=Queen p=Pawn k=King
test demo_debug_format ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Upvotes: 192
Reputation: 16630
While testing, standard output is not displayed. Don't use text messages for testing but assert!
, assert_eq!
, and fail!
instead. Rust's unit test system can understand these but not text messages.
The test you have written will pass even if something goes wrong. Let's see why:
read_to_end
's signature is
fn read_to_end(&mut self) -> IoResult<Vec<u8>>
It returns an IoResult
to indicate success or error. This is just a type def for a Result
whose error value is an IoError
. It's up to you to decide how an error should be handled. In this case, we want the task to fail, which is done by calling unwrap
on the Result
.
This will work:
let contents = File::open(&Path::new("message.txt"))
.read_to_end()
.unwrap();
unwrap
should not be overused though.
Upvotes: 13