Warum nicht drucken! in Rust Unit Tests arbeiten?

284

Ich habe die folgende Methode und den folgenden Komponententest implementiert:

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

Ich führe den Unit-Test folgendermaßen aus:

rustc --test app.rs; ./app

Ich könnte das auch mit laufen lassen

cargo test

Ich erhalte eine Nachricht zurück, dass der Test bestanden wurde, der println!jedoch nie auf dem Bildschirm angezeigt wird. Warum nicht?

Ruipacheco
quelle

Antworten:

327

Dies liegt daran, dass Rust-Testprogramme den Standard erfolgreicher Tests verbergen, damit die Testausgabe aufgeräumt wird. Sie können dieses Verhalten deaktivieren, indem Sie die --nocaptureOption an die Testbinärdatei übergeben oder an cargo test:

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

Tests aufrufen:

% 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

Wenn die Tests jedoch fehlschlagen, wird ihre Standardausgabe gedruckt, unabhängig davon, ob diese Option vorhanden ist oder nicht.

Vladimir Matveev
quelle
10
Sie haben erwähnt, dass die --nocaptureOption an übergeben wurde cargo test, aber die Fracht erkennt diese Flagge für mich nicht (unter Verwendung der neuesten Nacht von rustup.sh). Bist du sicher, dass es funktionieren sollte?
Jim Garrison
42
@ JimGarrison, in der Tat gibt es ein Problem . In der Zwischenzeit können Sie verwenden cargo test -- --nocapture, es sollte funktionieren.
Vladimir Matveev
4
Vielen Dank! Ich habe nichts mit dieser Frage zu tun, aber das hat mir auch geholfen, herauszufinden, wie ich auch cargo test [--] --benchzur Arbeit komme !
Jim Garrison
6
@Nashenas, die Option heißt nocapture, nicht no-capture.
Vladimir Matveev
1
Hat jemand herausgefunden, wie beim Debuggen in Visual Studio Code in Windows gedruckt werden soll? Die folgende Aufgabe wird nicht in der Popup-Shell gedruckt: Debugger "Frachttest --no-run - --nocapture". Beachten Sie die Verwendung des No-Run-Arguments, obwohl es in keiner Weise einen Unterschied zu machen scheint. Ich sehe nur "1 Test ausführen". Umständliche Werkzeuge.
David
75

TL; DR

$ cargo test -- --nocapture

Mit folgendem Code:

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

Führen Sie dann Folgendes aus:

 $ cargo test -- --nocapture

Und du solltest sehen

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
superlogisch
quelle
cargo test -- --no-capturefunktioniert nicht mehr. Ich erhalte die folgende Fehlermeldung:thread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
Nashenas
Ich frage mich, ob dieses Problem github.com/rust-lang/cargo/issues/1377 das Problem ist.
Superlogical
5
Wie bereits in früheren Kommentaren erwähnt, ist dies --nocapturenicht der Fall --no-capture. Dies ist jedoch ein völlig offensichtlicher Fehler bei den meisten Befehlszeilenkonventionen, auf die wir stoßen. Ich habe diese Option genau so verwendet, wie in dieser Antwort in Rost 1.1 (Fracht 0.2.0) beschrieben, und sie hat genau wie angegeben funktioniert.
Glenn McAllister
10

println!()Verwenden Sie die Flags colorund nocapturein, um Ausdrucke mit den Testergebnissen einzuschließen und Farben für diese beizubehalten cargo test.

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

(Frachtversion: 0.13.0 pro Nacht)

nate
quelle
6

Während des Tests wird die Standardausgabe nicht angezeigt. Nicht - Textnachricht zum Testen verwenden , aber assert!, assert_eq!und fail!stattdessen. Das Unit-Test-System von Rust kann diese, aber keine Textnachrichten verstehen.

Der von Ihnen geschriebene Test besteht auch dann, wenn etwas schief geht. Mal sehen warum:

read_to_endDie Unterschrift ist fn read_to_end(&mut self) -> IoResult<Vec<u8>>

Es wird ein zurückgegeben IoResult, um Erfolg oder Fehler anzuzeigen. Dies ist nur ein Typ def für a, Resultdessen Fehlerwert ein ist IoError. Es liegt an Ihnen, zu entscheiden, wie ein Fehler behandelt werden soll. In diesem Fall möchten wir, dass die Aufgabe fehlschlägt. Dies erfolgt durch Aufrufen unwrapvon Result.

Das wird funktionieren:

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

unwrap sollte aber nicht überbeansprucht werden.

AB
quelle