Как подавить вывод из нескольких потоков при запуске грузового теста? - PullRequest
0 голосов
/ 26 ноября 2018

Если я выполню приведенные ниже тестовые случаи с cargo test, вывод one_thread_test будет подавлен, как указано в документации.

Однако вывод из multi_thread_test появится в stdout.Можно ли сопоставить поведение однопоточных и многопоточных тестовых случаев?

#[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();
    }
}

1 Ответ

0 голосов
/ 26 ноября 2018

Вот быстрый и грязный обходной путь.

Он работает, отправляя сообщения получателю, принадлежащему структуре в основном потоке.Приемник печатает все накопленные сообщения при его отбрасывании - это важно, чтобы паника, вызванная ошибочными утверждениями, не помешала печати. ​​

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.

...