【问题标题】:How do I suppress output from multiple threads when running cargo test?运行货物测试时如何抑制多个线程的输出?
【发布时间】:2019-04-28 02:09:25
【问题描述】:

如果我使用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();
    }
}

【问题讨论】:

  • @PeterHall 问题是cargo 在多线程测试用例中没有像上面的链接那样隐藏标准输出。
  • 哦,我明白了。您可以通过实现自己的print 来解决它,它写入共享缓冲区,并且只从主线程中的缓冲区打印。不过可能过于复杂..

标签: unit-testing debugging rust rust-cargo


【解决方案1】:

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

它通过向主线程中的结构所拥有的接收器发送消息来工作。接收器在丢弃时打印所有累积的消息 - 这很重要,因此断言失败引起的恐慌不会阻止打印。

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

【讨论】:

  • 但是 cargo 中的这个错误是我应该报告这个问题,还是这个有意的行为,并且应该在由于某种原因在我的测试中需要多线程时总是使用你的 hack?
  • 我不确定这是否是技术上的错误。但可能会这样看,报告它并没有什么坏处。
  • 感谢您的回答和回复,我在这里提交问题:github.com/rust-lang/cargo/issues/6350 并会等待一天才能接受答案,可能有人提出其他建议。
猜你喜欢
  • 2021-08-18
  • 2021-08-11
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 2016-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多