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?
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
:
#[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.
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
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.
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)
来源:https://stackoverflow.com/questions/25106554/why-doesnt-println-work-in-rust-unit-tests