web-dev-qa-db-fra.com

Pourquoi ne pas imprimer! travailler dans Rust tests unitaires?

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 courir avec

cargo test

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

219
ruipacheco

Cela est dû au fait que Rust programmes de test masquent la sortie standard des tests réussis afin que la sortie de test soit bien rangée. Vous pouvez désactiver ce comportement en passant l'option --nocapture au test binaire ou à cargo test:

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

Invocation 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, leur sortie standard sera imprimée, que cette option soit présente ou non.

257
Vladimir Matveev

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

Puis lancez ce qui suit:

 $ cargo test -- --nocapture

Et vous devriez 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
61
superlogical

Pour inclure les impressions avec println!() et conserver les couleurs pour les résultats du test, utilisez les indicateurs color et nocapture dans cargo test.

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

(version cargo: 0.13.0 tous les soirs)

5
nate

Lors du test, la sortie standard n'est pas affichée. N'utilisez pas les messages texte pour les tests, mais plutôt assert!, assert_eq! et fail!. Le système de test unitaire de Rust peut comprendre ces messages, mais pas les messages texte.

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

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

Il retourne un IoResult pour indiquer un succès ou une erreur. Ceci est juste un type def pour un Result dont la valeur d'erreur est un IoError. C'est à vous de décider comment une erreur doit être traitée. Dans ce cas, nous voulons que la tâche échoue, ce qui est fait en appelant unwrap sur le Result.

Cela fonctionnera:

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

unwrap ne devrait cependant pas être surutilisé.

4
A.B.