Dlaczego nie drukujemy! praca w testach jednostkowych rdzy?

Zaimplementowałem następującą metodę i test jednostkowy:

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);
}

Przeprowadzam test jednostkowy w ten sposób:

rustc --test app.rs; ./app

Mógłbym też uruchomić to z

cargo test

Otrzymuję wiadomość, że test przeszedł pomyślnie, ale println! nigdy nie jest wyświetlany na ekranie. Dlaczego nie?

 353
Author: Shepmaster, 2014-08-03

5 answers

Dzieje się tak, ponieważ programy testujące Rust ukrywają stdout pomyślnych testów, aby wynik testu był uporządkowany. Możesz wyłączyć to zachowanie, przekazując opcję --nocapture do testowego pliku binarnego lub do cargo test:

#[test]
fn test() {
    println!("Hidden output")
}

Wywołanie testów:

% 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

Jeśli testy nie powiodą się, ich wyjście standardowe zostanie wydrukowane niezależnie od tego, czy ta opcja jest obecna, czy nie.

 394
Author: Vladimir Matveev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-13 01:32:19

TL;DR

$ cargo test -- --nocapture

O następującym kodzie:

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

Następnie uruchom następujące:

 $ cargo test -- --nocapture

I powinieneś zobaczyć

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
 90
Author: superlogical,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-13 02:14:26

Aby dołączyć wydruki z println!() i zachować kolory dla wyników testu, użyj znaczników color i nocapture w cargo test.

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

(wersja cargo: 0.13.0)

 17
Author: nate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-02 05:15:21

Dla obecnych i przyszłych widzów tego pytania, --show-output jest droga do zrobienia, jak wspomniano przez @l-f w komentarzu do innej odpowiedzi. Ale wygląda na to, że brakuje jej w dokumentacji.

Więc pełna Komenda to cargo test -- --show-output

 8
Author: Raphael D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-25 20:36:23

Podczas testowania standardowe wyjście nie jest wyświetlane. Nie używaj SMS-ów do testowania, ale assert!, assert_eq!, i fail! zamiast tego. System testów jednostkowych Rusta może je zrozumieć, ale nie Wiadomości tekstowe.

Test, który napisałeś zda, nawet jeśli coś pójdzie nie tak. Zobaczmy dlaczego:

read_to_end's podpis jest fn read_to_end(&mut self) -> IoResult<Vec<u8>>

Zwraca IoResult, aby wskazać sukces lub błąd. Jest to po prostu Typ def dla Result, którego wartością błędu jest IoError. To od Ciebie zależy, jak błąd powinien zostać rozwiązany. W tym przypadku chcemy, aby zadanie nie powiodło się, co odbywa się poprzez wywołanie {[9] } na Result.

To zadziała:

let contents = File::open(&Path::new("message.txt"))
    .read_to_end()
    .unwrap();

unwrap nie należy jednak nadużywać.

 5
Author: A.B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-03 17:11:32