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

eyh26e7m  于 2022-12-23  发布在  其他
关注(0)|答案(8)|浏览(532)

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

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!从来没有显示在屏幕上。为什么不呢?

mbyulnm0

mbyulnm01#

这是因为Rust测试程序隐藏了成功测试的stdout,以使测试输出整洁。你可以通过将--nocapture选项传递给test二进制文件或cargo test来禁用此行为(但是,在本例中 after---见下文):

#[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

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

vvppvyoh

vvppvyoh2#

靶病变; 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
ffvjumwh

ffvjumwh3#

正如L.F.提到的,--show-output是要走的路。

$ cargo test -- --show-output

其他显示标志在货物测试文件的显示选项中提及。

htrmnn0y

htrmnn0y4#

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

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

(货运版本:每晚0.13.0)

sxissh06

sxissh065#

测试时,不显示标准输出。不要使用文本消息进行测试,而是使用assert!assert_eq!fail!。Rust的单元测试系统可以理解这些消息,但不能理解文本消息。
即使出现问题,您编写的测试也会通过。让我们看看原因:
read_to_end的签名是fn read_to_end(&mut self) -> IoResult<Vec<u8>>
它返回一个IoResult来指示成功或错误。这只是一个Result的类型def,它的错误值是一个IoError。由您来决定如何处理错误。在本例中,我们希望任务失败,这是通过在Result上调用unwrap来完成的。
这将工作:

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

但是不应该过度使用unwrap

o8x7eapl

o8x7eapl6#

注意,现代的解决方案(cargo test -- --show-output)在你的函数的文档字符串中的Markdown代码栅栏中定义的文档测试中不起作用。只有在一个具体的#[test]块中完成的println!(等等)语句才会被考虑。

pkwftd7m

pkwftd7m7#

为什么?我不知道,但是有个小黑客

rslzwgfq

rslzwgfq8#

测试框架很可能正在捕获测试输出,而没有将其打印到标准输出。在使用cargo test运行测试时,只有在测试失败时才会捕获并显示每个测试的输出。如果您希望查看测试的输出,可以在使用cargo test运行测试时使用--nocapture标志。如下所示:

cargo test -- --nocapture

或者你也可以在测试函数中使用println!宏来把输出打印到标准输出中,比如:

#[test]
 fn test_read_file() {
    let path = &Path::new("/etc/hosts");
    println!("{:?}", path);
    read_file(path);
    println!("The test passed!");
}

相关问题