【问题标题】:Why doesn't println! work in Rust unit tests?为什么不打印!在 Rust 单元测试中工作?
【发布时间】:2014-09-26 05:03:53
【问题描述】:

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

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

【问题讨论】:

    标签: rust println


    【解决方案1】:

    这是因为 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
    

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

    【讨论】:

    • 您提到将 --nocapture 选项传递给 cargo test,但 cargo 无法为我识别此标志(使用 rustup.sh 的最新夜间)。你确定它应该工作吗?
    • @JimGarrison,确实是there is an issue。同时你可以使用cargo test -- --nocapture,它应该可以工作。
    • 谢谢!与这个问题无关,但这也帮助我弄清楚如何让cargo test [--] --bench 也能工作!
    • @Nashenas,该选项称为nocapture,而不是no-capture
    • @Anonyme2000 --nocapture 在 2018 版中仍然有效。 --show-output 是另一个选项,它以更易于查看的格式组织输出。
    【解决方案2】:

    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
    • 不知这个问题github.com/rust-lang/cargo/issues/1377是不是有问题?
    • 正如之前的 cmets 中所指出的,选项是 --nocapture,而不是 --no-capture。但是,鉴于我们经常遇到的大多数命令行约定,这是一个完全明显的错误。我只是完全按照 rust 1.1 (cargo 0.2.0) 中的这个答案中的描述使用了这个选项,它的工作原理和宣传的完全一样。
    【解决方案3】:

    作为mentioned by L. F.--show-output 是要走的路。

    $ cargo test -- --show-output
    

    其他显示标志为mentioned in the documentation of cargo test in display-options

    【讨论】:

    • 注意--show-output 仅打印成功测试的标准输出。
    • 这很有帮助。奇怪的额外——在 CL 上让我很困惑。我只需要运行一个测试并显示输出。看起来像 $ cargo test [test_name] -- --show-output
    【解决方案4】:

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

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

    (货运版本:每晚 0.13.0)

    【讨论】:

      【解决方案5】:

      测试时,不显示标准输出。不要使用短信进行测试,而是使用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 不应该被过度使用。

      【讨论】:

      • 真实信息,但不是 OP 的答案。
      猜你喜欢
      • 2016-09-08
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 2010-11-21
      • 2017-09-20
      • 1970-01-01
      • 2023-01-30
      相关资源
      最近更新 更多