Чому не println! робота в тестах Rust Unit?


285

Я реалізував наступний метод та одиничний тест:

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

Я запускаю тестовий апарат таким чином:

rustc --test app.rs; ./app

Я також міг би це запустити

cargo test

Я отримую повідомлення про тест пройденого, але println!на екрані він ніколи не відображається. Чому ні?

Відповіді:


327

Це відбувається тому, що тестові програми Rust приховують склад успішних тестів, щоб тестовий результат був акуратним. Ви можете відключити цю поведінку, перейшовши --nocaptureопцію в тестовий двійковий файл або на cargo test:

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

Викликаючі тести:

% 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

Якщо тести не вдаються, однак їх stdout буде надруковано незалежно від того, є ця опція чи ні.


10
Ви згадали про те, --nocaptureщоб передати цю опцію cargo test, але вантаж не розпізнає цей прапор для мене (використовуючи останню ніч з rustup.sh). Ви впевнені, що це має працювати?
Джим Гаррісон

42
@JimGarrison, дійсно, в цьому питання є . Тим часом ви можете використовувати cargo test -- --nocapture, це має спрацювати.
Володимир Матвєєв

4
Дякую! не пов'язаний з цим питанням, але це також допомогло мені зрозуміти, як влаштуватись cargo test [--] --benchна роботу!
Джим Гаррісон

6
@Nashenas, опція викликається nocapture, ні no-capture.
Володимир Матвєєв

1
Хтось придумав, як друкувати при налагодженні коду Visual Studio у Windows? Наступне завдання не надрукує на спливаючу оболонку: налагоджувач "тест вантажу - не запущений - --незахоплення". Зверніть увагу на використання аргументу без запуску, хоча це, схоже, не має ніякого значення. Все, що я бачу - це "запуск 1 тесту". Незграбний інструментарій.
Девід

75

TL; DR

$ cargo test -- --nocapture

З наступним кодом:

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

Потім запустіть наступне:

 $ cargo test -- --nocapture

І ти повинен побачити

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

cargo test -- --no-captureбільше не працює. Я отримую таку помилку:thread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
Nashenas

Цікаво, чи це проблема github.com/rust-lang/cargo/isissue/1377 ?
суперлогічний

5
Як було зазначено в попередніх коментарях, варіант є --nocapture, ні --no-capture. Однак це цілком очевидна помилка, зважаючи на більшість конвенцій командного рядка, до яких ми зазвичай стикаємося. Я просто використав цей варіант саме так, як описано у цій відповіді в іржі 1.1 (вантаж 0.2.0), і він працював точно так, як оголошено.
Глен МакАллістер

10

Для включення роздруківки println!()та збереження кольорів для результатів тестування використовуйте позначки colorта nocaptureпозначки cargo test.

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

(вантажна версія: 0,13,0 щоночі)


6

Під час тестування стандартний вихід не відображається. Не використовуйте текстові повідомлення для тестування , але assert!, assert_eq!і fail!замість цього. Тестова система Раста може зрозуміти ці, але не текстові повідомлення.

Тест, який ви написали, пройде, навіть якщо щось піде не так. Давайте розберемося, чому:

read_to_endПідпис є fn read_to_end(&mut self) -> IoResult<Vec<u8>>

Він повертає " IoResultвказувати на успіх чи помилку". Це просто тип def для Resultякого значення помилки - an IoError. Ви вирішуєте, як поводитися з помилкою. У цьому випадку ми хочемо, щоб завдання провалилося, що робиться за допомогою виклику unwrapна Result.

Це спрацює:

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

unwrap не варто занадто зловживати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.