Unit testing 在运行cargo测试时,如何抑制来自多个线程的输出?
如果我使用Unit testing 在运行cargo测试时,如何抑制来自多个线程的输出?,unit-testing,debugging,rust,rust-cargo,Unit Testing,Debugging,Rust,Rust Cargo,如果我使用cargo test执行以下测试用例,则one_thread_test的输出将被抑制,如文档中所述 但是,多线程测试的输出将出现在标准输出上。是否可以匹配单线程和多线程测试用例的行为 #[test] fn one_thread_test() { println!("A"); println!("B"); } #[test] fn multi_thread_test() { use std::thread; let mut threads = vec!
cargo test
执行以下测试用例,则one_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();
}
}
这里有一个快速而肮脏的解决方法
它的工作原理是将消息发送给主线程中结构所拥有的接收方。接收者在丢弃消息时打印所有累积的消息——这一点很重要,这样由失败的断言引起的恐慌就不会阻止打印
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);
}
}
}
为了发送要打印的消息,您必须为每个线程获得一个发送者
:
#[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();
}
}
当打印机
超出范围时,实际打印发生。它位于主线程中,因此在成功测试期间不会打印,除非指定了--nocapture
。@PeterHall问题是cargo
没有像上面多线程测试案例中的链接那样隐藏stdout。哦,我明白了。您可以通过实现自己的print
(写入共享缓冲区,并且只从主线程中的缓冲区打印)来解决此问题。可能过于复杂。但这是cargo
中的错误,我应该报告问题,还是这种有意的行为,并且应该在出于某种原因我需要在测试中使用多线程时始终使用您的黑客?我不确定这在技术上是否是错误。谢谢你们的回答和回复,我在这里提交问题:在接受答案之前,我会等一天,也许有人会提出其他建议。
#[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();
}
}