なぜprintlnしないのですか?Rust単体テストで機能しますか?


284

次のメソッドと単体テストを実装しました。

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テストプログラムが成功したテストのstdoutを隠して、テスト出力を整頓するために発生します。この動作を無効にするには、--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に渡すとのことですが、貨物はこのフラグを認識しません(rustup.shの最新のナイトリーを使用しています)。動作しますか?
ジムギャリソン

42
@JimGarrison、確かに、それには問題があります。その間、あなたは使うことができますcargo test -- --nocapture、それはうまくいくはずです。
Vladimir Matveev 2014

4
ありがとう!この質問とは無関係ですが、それも私cargo test [--] --benchが仕事に就く方法を理解するのに役立ちました!
ジムギャリソン

6
@Nashenas、オプションはではnocaptureなく、呼び出されますno-capture
Vladimir Matveev 2015

1
ウィンドウのVisual Studio Codeでデバッグするときに印刷する方法を見つけた人はいますか?次のタスクは、ポップアップシェルに出力しません:「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

cargo test -- --no-capture動作しなくなりました。次のエラーが表示されますthread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
。–ナシェナ

この問題github.com/rust-lang/cargo/issues/1377に問題があるのでしょうか?
超論理的な2015

5
以前のコメントで指摘されているように、オプションはであり--nocapture、ではありません--no-capture。しかし、私たちが遭遇する傾向のあるほとんどのコマンドライン規則を考えると、これは完全に明らかな間違いです。私はこのオプションをrust 1.1(cargo 0.2.0)のこの回答で説明されているとおりに使用しただけで、宣伝どおりに機能しました。
Glenn McAllister 2015

10

println!()テスト結果の出力を含め、色を保持するにはcolor、でnocaptureフラグとフラグを使用しcargo 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成功またはエラーを示すを返します。これはResult、エラー値がであるのタイプ定義IoErrorです。エラーの処理方法を決定するのはあなた次第です。この場合、タスクを失敗させる必要があります。これは、を呼び出すことによって実行さunwrapれますResult

これは動作します:

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

unwrap 使いすぎてはいけません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.