Почему не печатает! работать в Rust юнит-тестах?

286

Я реализовал следующий метод и модульный тест:

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!никогда не отображается на экране. Почему нет?

ruipacheco
источник

Ответы:

328

Это происходит потому, что тестовые программы 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

Однако, если тесты не пройдены, их стандартный вывод будет напечатан независимо от того, присутствует эта опция или нет.

Владимир Матвеев
источник
10
Вы упомянули, что передавали эту --nocaptureопцию cargo test, но Cargo не распознает этот флаг для меня (используется последняя ночная версия от rustup.sh). Вы уверены, что это должно работать?
Джим Гаррисон
42
@JimGarrison, действительно, есть проблема по этому поводу . Тем временем вы можете использовать cargo test -- --nocapture, это должно работать.
Владимир Матвеев
4
Спасибо! не имеет отношения к этому вопросу, но это также помогло мне понять, как добраться cargo test [--] --benchдо работы тоже!
Джим Гаррисон
6
@Нашена, вариант называется nocapture, нет no-capture.
Владимир Матвеев
1
Кто-нибудь разобрался, как печатать при отладке в Visual Studio Code в windows? Следующая задача не выводится во всплывающую оболочку: отладчик «cargo test --no-run - --nocapture». Обратите внимание на использование аргумента no-run, хотя он, похоже, не имеет значения в любом случае. Все, что я вижу, это «запуск 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
superlogical
источник
cargo test -- --no-captureбольше не работает. Я получаю следующую ошибку:thread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
Нашенас
Интересно, это проблема github.com/rust-lang/cargo/issues/1377 ?
суперлогично
5
Как было указано в предыдущих комментариях, вариант есть --nocapture, нет --no-capture. Тем не менее, это совершенно очевидная ошибка, если принять во внимание большинство соглашений командной строки, с которыми мы обычно сталкиваемся. Я просто использовал эту опцию точно так, как описано в этом ответе в ржавчине 1.1 (груз 0.2.0), и она работала именно так, как рекламируется.
Гленн Макаллистер
11

Чтобы включить распечатки println!()и сохранить цвета для результатов теста, используйте флаги colorи .nocapturecargo test

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

(грузовая версия: 0.13.0 ночью)

Нейт
источник
6

Во время тестирования стандартный вывод не отображается. Не используйте текстовые сообщения для тестирования , но assert!, assert_eq!и fail!вместо этого. Система модульного тестирования Rust может понимать эти, но не текстовые сообщения.

Тест, который вы написали, пройдет, даже если что-то пойдет не так. Посмотрим почему:

read_to_endподпись fn read_to_end(&mut self) -> IoResult<Vec<u8>>

Возвращает, IoResultчтобы указать успех или ошибку. Это просто тип def для Resultзначения ошибки которого является IoError. Вам решать, как обрабатывать ошибку. В этом случае, мы хотим , чтобы задача потерпеть неудачу, что делается путем вызова unwrapна Result.

Это будет работать:

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

unwrap не следует злоупотреблять, хотя.

AB
источник