623 Stimmen

Warum funktioniert println! nicht in Rust-Einheitstests?

Ich habe die folgende Methode und den Unittest 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 Unittest auf folgende Weise aus:

rustc --test app.rs; ./app

Ich könnte es auch so ausführen

cargo test

Ich erhalte eine Nachricht, dass der Test bestanden hat, aber das println!-Statement wird nie auf dem Bildschirm angezeigt. Warum nicht?

709voto

Vladimir Matveev Punkte 111699

Dies geschieht, weil Rust-Testprogramme die Standardausgabe erfolgreicher Tests ausblenden, damit die Testausgabe ordentlich aussieht. Sie können dieses Verhalten deaktivieren, indem Sie die Option --nocapture an das Test-Binary oder an cargo test übergeben (aber in diesem Fall nach -- – siehe unten):

#[test]
fn test() {
    println!("Versteckte Ausgabe")
}

Tests aufrufen:

% rustc --test main.rs; ./main

1 Test wird ausgeführt
Test test ... ok

Testergebnis: ok. 1 erfolgreich; 0 fehlgeschlagen; 0 ignoriert; 0 gemessen

% ./main --nocapture

1 Test wird ausgeführt
Versteckte Ausgabe
Test test ... ok

Testergebnis: ok. 1 erfolgreich; 0 fehlgeschlagen; 0 ignoriert; 0 gemessen

% cargo test -- --nocapture

1 Test wird ausgeführt
Versteckte Ausgabe
Test test ... ok

Testergebnis: ok. 1 erfolgreich; 0 fehlgeschlagen; 0 ignoriert; 0 gemessen

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

179voto

superlogical Punkte 13526

TL;DR

$ cargo test -- --nocapture

Mit dem folgenden 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);
}

Dann führen Sie Folgendes aus:

 $ cargo test -- --nocapture

Und Sie sollten 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

72voto

Vorwort: Diese Antwort spiegelt eine Änderung in Rust 1.41 wider ("Sie können jetzt das Argument --show-output an Test-Binärdateien übergeben, um die Ausgabe erfolgreicher Tests anzuzeigen." laut Änderungsprotokoll)


Wie von L. F. erwähnt, ist --show-output der richtige Weg.

$ cargo test -- --show-output

Weitere Anzeigeoptionen sind in der Dokumentation von cargo test unter Display-Optionen erwähnt.

28voto

nate Punkte 733

Um Ausdrucke mit println!() einzuschließen und die Farben für die Testergebnisse beizubehalten, verwenden Sie die Flags color und nocapture in cargo test.

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

(cargo version: 0.13.0 nightly)

13voto

A.B. Punkte 15244

Beim Testen wird die Standardausgabe nicht angezeigt. Verwenden Sie beim Testen keine Textnachrichten, sondern assert!, assert_eq! und fail! stattdessen. Rusts Einheitstestsystem kann diese verstehen, aber keine Textnachrichten.

Der von Ihnen geschriebene Test wird bestehen, auch wenn etwas schief geht. Schauen wir mal warum:

Die Signatur von read_to_end ist fn read_to_end(&mut self) -> IoResult>

Es gibt ein IoResult zurück, um Erfolg oder Fehler anzuzeigen. Dies ist nur eine Typdefinition für ein Result, dessen Fehlerwert ein IoError ist. Es liegt an Ihnen zu entscheiden, wie Fehler behandelt werden sollen. In diesem Fall möchten wir, dass die Aufgabe fehlschlägt, was durch Aufrufen von unwrap auf dem Result erfolgt.

Dies wird funktionieren:

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

unwrap sollte jedoch nicht übermäßig verwendet werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X