Pourquoi n'imprime pas! travailler dans les tests unitaires de Rust?

286

J'ai implémenté la méthode et le test unitaire suivants:

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

Je lance le test unitaire de cette façon:

rustc --test app.rs; ./app

Je pourrais aussi faire ça avec

cargo test

Je reçois un message disant que le test a réussi, mais il println!ne s'affiche jamais à l'écran. Pourquoi pas?

ruipacheco
la source

Réponses:

328

Cela se produit car les programmes de test Rust masquent la sortie standard des tests réussis pour que la sortie du test soit bien rangée. Vous pouvez désactiver ce comportement en passant l' --nocaptureoption au binaire de test ou à cargo test:

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

Appel de tests:

% 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

Si les tests échouent, cependant, leur sortie standard sera imprimée, que cette option soit présente ou non.

Vladimir Matveev
la source
10
Vous avez mentionné le passage de l' --nocaptureoption à cargo test, mais cargo ne reconnaît pas ce drapeau pour moi (en utilisant la dernière nuit de rustup.sh). Êtes-vous sûr que cela devrait fonctionner?
Jim Garrison
42
@ JimGarrison, en effet, il y a un problème à ce sujet. Pendant ce temps, vous pouvez utiliser cargo test -- --nocapture, cela devrait fonctionner.
Vladimir Matveev
4
Merci! sans rapport avec cette question, mais cela m'a aussi aidé à comprendre comment me rendre cargo test [--] --benchau travail aussi!
Jim Garrison
6
@Nashenas, l'option est appelée nocapture, non no-capture.
Vladimir Matveev
1
Quelqu'un a-t-il compris comment imprimer lors du débogage dans Visual Studio Code dans Windows? La tâche suivante ne s'imprime pas dans le shell contextuel: débogueur "test cargo - no-run - --nocapture". Notez l'utilisation de l'argument no-run bien qu'il ne semble pas faire de différence dans les deux cas. Tout ce que je vois c'est "exécuter 1 test". Outillage maladroit.
David
75

TL; DR

$ cargo test -- --nocapture

Avec le code suivant:

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

Exécutez ensuite ce qui suit:

 $ cargo test -- --nocapture

Et tu devrais voir

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
superlogique
la source
cargo test -- --no-capturene fonctionne plus. thread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
J'obtiens l'
Je me demande si ce problème github.com/rust-lang/cargo/issues/1377 est le problème?
Superlogical
5
Comme cela a été souligné dans les commentaires précédents, l'option ne l'est --nocapturepas --no-capture. Cependant, c'est une erreur tout à fait évidente à faire étant donné la plupart des conventions de ligne de commande que nous avons tendance à rencontrer. J'ai juste utilisé cette option exactement comme décrit dans cette réponse dans rust 1.1 (cargo 0.2.0) et cela a fonctionné exactement comme annoncé.
Glenn McAllister
11

Pour inclure les impressions avec println!()et conserver les couleurs des résultats du test, utilisez les drapeaux coloret .nocapturecargo test

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

(version cargo: 0.13.0 la nuit)

nate
la source
6

Pendant le test, la sortie standard n'est pas affichée. Ne pas utiliser des messages texte pour tester mais assert!, assert_eq!et au fail!lieu. Le système de test unitaire de Rust peut comprendre ces messages, mais pas les SMS.

Le test que vous avez écrit passera même si quelque chose ne va pas. Voyons pourquoi:

read_to_endla signature de fn read_to_end(&mut self) -> IoResult<Vec<u8>>

Il renvoie un IoResultpour indiquer le succès ou l'erreur. Il s'agit simplement d'un type def pour un Resultdont la valeur d'erreur est un IoError. C'est à vous de décider comment traiter une erreur. Dans ce cas, nous voulons que la tâche échoue, ce qui se fait en appelant unwraple Result.

Cela fonctionnera:

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

unwrap ne doit cependant pas être surutilisé.

UN B
la source