unit-testing - 运行 cargo test 时如何抑制多线程的输出?

标签 unit-testing debugging rust rust-cargo

如果我使用 cargo test 执行以下测试用例,one_thread_test 的输出将被抑制,如文档中所述。

但是 multi_thread_test 的输出将出现在标准输出上。是否可以匹配单线程和多线程测试用例的行为?

#[test]
fn one_thread_test() {
    println!("A");
    println!("B");
}

#[test]
fn multi_thread_test() {
    use std::thread;

    let mut threads = vec![];
    for _ in 0..100 {
        let t = thread::spawn(move || {
            println!("from thread");
        });
        threads.push(t);
    }
    for thread in threads {
        thread.join().unwrap();
    }
}

最佳答案

这是一个快速而肮脏的解决方法。

它的工作原理是将消息发送到主线程中结构体拥有的接收器。接收器在它被丢弃时打印所有累积的消息 - 这很重要,这样由失败的断言引起的 panic 不会阻止打印。

use std::sync::mpsc::{channel, Sender, Receiver};

struct TestPrinter {
    receiver: Receiver<String>,
    sender: Sender<String>,
}

impl TestPrinter {
    fn new() -> TestPrinter {
        let (sender, receiver) = channel();
        TestPrinter { receiver, sender }
    }

    fn sender(&self) -> Sender<String> {
        self.sender.clone()
    }
}

impl Drop for TestPrinter {
    fn drop(&mut self) {
        while let Some(v) = self.receiver.try_recv().ok() {
            println!("later: {}", v);
        }
    }
}

还有一个方便的宏,感觉就像调用 println!:

macro_rules! myprint {
    ($send: expr, $($arg:tt)*) => { 
        (*&$send).send(format!($($arg)*));
     };
}  

为了发送消息进行打印,每个线程都有一个sender:

#[test]
fn multi_thread_test() {
    use std::thread;

    let mut threads = vec![];
    let printer = TestPrinter::new();

    for _ in 0..100 {
        let sender = printer.sender();
        let t = thread::spawn(move || {
            myprint!(sender, "from thread");
        });
        threads.push(t);
    }

    for thread in threads {
        thread.join().unwrap();
    }
}

实际打印发生在 printer 超出范围时。它位于主线程中,因此在成功测试期间不会打印,除非指定了 --nocapture

关于unit-testing - 运行 cargo test 时如何抑制多线程的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53480972/

相关文章:

php - 单元测试 cakephp 模型

css - 什么 CSS 设置解释了按钮和 div 在子垂直定位中的差异?

objective-c - 单击按钮以使用Xcode播放声音时调试器中的错误

visual-studio-code - 在 VSCode Web 扩展中加载 wasm

string - 如何从 Rust 中的另一个字符串中删除单个尾随字符串?

rust - Rust 支持哪些隐式数字转换?

c# - 使用我的 NuGet 包分发可重用测试类有哪些选项?

unit-testing - TFS 构建和测试影响

c# - TestDriven.Net 仅在文件中运行一个测试夹具

使用 Pydev 1.5 进行调试