为什么不println!在Rust单元测试中工作?


284

我已经实现了以下方法和单元测试:

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);
}

我以这种方式运行单元测试:

rustc --test app.rs; ./app

我也可以用

cargo test

我收到一条消息,说测试已通过,但println!从未显示在屏幕上。为什么不?

Answers:


327

发生这种情况是因为Rust测试程序隐藏了成功测试的标准,以便使测试输出整洁。您可以通过将--nocapture选项传递给测试二进制文件或来禁用此行为cargo test

#[test]
fn test() {
    println!("Hidden output")
}

调用测试:

% 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

但是,如果测试失败,则无论此选项是否存在,都将打印其标准输出。


10
您提到将--nocapture选项传递给cargo test,但是货物对我来说不识别此标志(使用rustup.sh的最新夜间报告)。您确定它应该工作吗?
Jim Garrison 2014年

42
@JimGarrison,确实存在一个问题。同时您可以使用cargo test -- --nocapture,它应该可以工作。
弗拉基米尔·马特维耶夫(Fladimir Matveev)2014年

4
谢谢!与这个问题无关,但这也帮助我弄清楚如何cargo test [--] --bench上班!
Jim Garrison 2014年

6
@Nashenas,该选项称为nocapture,而不是no-capture
弗拉基米尔·马特维夫

1
在Windows中的Visual Studio Code中调试时,有没有人想出如何打印?以下任务不会打印到弹出窗口外壳:“ cargo test --no-run---nocapture”调试器。请注意使用no-run参数,尽管这两种方法似乎都没有什么区别。我所看到的只是“运行1个测试”。笨拙的工具。
戴维(David)

75

TL; DR

$ cargo test -- --nocapture

使用以下代码:

#[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);
}

然后运行以下命令:

 $ cargo test -- --nocapture

你应该看到

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

cargo test -- --no-capture不再有效。我收到以下错误:thread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
Nashenas

我想知道这个问题github.com/rust-lang/cargo/issues/1377是问题吗?
超级逻辑2015年

5
正如前面的评论中指出的那样,该选项--nocapture不是--no-capture。但是,对于给定的大多数我们都会遇到的命令行约定,这是一个完全显而易见的错误。我只是完全按照rust 1.1(货物0.2.0)中的答案中的说明使用了此选项,它的工作方式与广告中所述的完全一样。
Glenn McAllister 2015年

10

要包含打印输出println!()并保持测试结果的颜色,请使用中的colornocapture标志cargo test

$ cargo test -- --color always --nocapture

(货运版本:每晚0.13.0)


6

测试期间,不显示标准输出。不要使用短信进行测试,但是assert!assert_eq!fail!代替。Rust的单元测试系统可以理解这些信息,但不能理解短信。

即使出现问题,您编写的测试也会通过。让我们看看为什么:

read_to_end的签名是 fn read_to_end(&mut self) -> IoResult<Vec<u8>>

它返回IoResult表示成功或错误。这只是Result其错误值是的类型def IoError。由您决定如何处理错误。在这种情况下,我们要失败的任务,这是通过调用unwrapResult

这将起作用:

let contents = File::open(&Path::new("message.txt"))
    .read_to_end()
    .unwrap();

unwrap 但不应过度使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.