Dlaczego nie drukuje! pracować w testach jednostkowych Rust?

285

Wdrożył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);
}

Test jednostkowy uruchamiam w ten sposób:

rustc --test app.rs; ./app

Mógłbym to również uruchomić

cargo test

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

ruipacheco
źródło

Odpowiedzi:

327

Dzieje się tak, ponieważ programy testowe Rust ukrywają standardowe testy zakończone sukcesem, aby wyniki testów były uporządkowane. Możesz wyłączyć to zachowanie, przekazując --nocaptureopcję do pliku binarnego testowego lub cargo test:

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

Wywoływanie 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 się nie powiodą, ich standardowe wyjście zostanie wydrukowane niezależnie od tego, czy ta opcja jest obecna, czy nie.

Vladimir Matveev
źródło
10
Wspomniałeś o przekazaniu --nocaptureopcji cargo test, ale ładunek nie rozpoznaje dla mnie tej flagi (korzystając z najnowszej nocy z rustup.sh). Jesteś pewien, że to powinno działać?
Jim Garrison,
42
@JimGarrison, rzeczywiście jest w tym problem . Tymczasem możesz korzystać cargo test -- --nocapture, powinno działać.
Vladimir Matveev,
4
dzięki! niezwiązane z tym pytaniem, ale pomogło mi to również wymyślić, jak dostać się cargo test [--] --benchdo pracy!
Jim Garrison,
6
@Nashenas, opcja jest wywoływana nocapture, a nie no-capture.
Vladimir Matveev
1
Czy ktoś wymyślił, jak drukować podczas debugowania w programie Visual Studio Code w systemie Windows? Następujące zadanie nie drukuje się w wyskakującym okienku: debugger „test ładunku - nie uruchamia się - --nocapture”. Zwróć uwagę na użycie argumentu braku uruchamiania, chociaż nie wydaje się, aby miało to jakąkolwiek różnicę. Widzę tylko „uruchomienie 1 testu”. Niezręczne oprzyrządowanie.
David
75

TL; DR

$ cargo test -- --nocapture

Z następującym kodem:

#[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 czynności:

 $ 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
superlogiczny
źródło
cargo test -- --no-capturenie działa. thread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
Pojawia się
Zastanawiam się, czy problem to github.com/rust-lang/cargo/issues/1377 ?
superlogiczny
5
Jak wskazano w poprzednich komentarzach, opcja jest --nocaptureinna --no-capture. Jest to jednak całkowicie oczywisty błąd, biorąc pod uwagę większość konwencji wiersza poleceń, z którymi zwykle się spotykamy. Właśnie użyłem tej opcji dokładnie tak, jak opisano w tej odpowiedzi w rdzeniu 1.1 (ładunek 0.2.0) i działała dokładnie tak, jak reklamowano.
Glenn McAllister
10

Aby dołączyć wydruki println!()i zachować kolory dla wyników testu, użyj flag colori .nocapturecargo test

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

(wersja cargo: 0.13.0 na noc)

Nate
źródło
6

Podczas testowania standardowe wyjście nie jest wyświetlane. Nie używać wiadomości tekstowych do testowania, ale assert!, assert_eq!i fail!zamiast tego. System testów jednostkowych Rust może zrozumieć te, ale nie SMS-y.

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

read_to_endpodpis jest fn read_to_end(&mut self) -> IoResult<Vec<u8>>

Zwraca an, IoResultaby wskazać sukces lub błąd. Jest to po prostu def dla typu, dla Resultktórego wartością błędu jest an IoError. To Ty decydujesz, jak rozwiązać błąd. W tym przypadku chcemy zadanie nie, co jest realizowane poprzez wywołanie unwrapna Result.

To zadziała:

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

unwrap nie należy jednak nadużywać.

AB
źródło