Neden println! birim testlerinde ne işe yarar?


286

Aşağıdaki yöntemi ve birim testini uyguladım:

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

Birim testini şu şekilde çalıştırıyorum:

rustc --test app.rs; ./app

Bunu da çalıştırabilirim

cargo test

Testin geçtiğini söyleyen bir mesaj alıyorum ama println!ekranda hiçbir zaman görüntülenmiyor. Neden olmasın?

Yanıtlar:


328

Bunun nedeni, Rust test programlarının test çıkışının düzenli olması için başarılı testlerin stdout'unu gizlemesidir. --nocaptureSeçeneği test ikili dosyasına geçirerek veya aşağıdakilere yaparak bu davranışı devre dışı bırakabilirsiniz cargo test:

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

Testleri başlatma:

% 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

Ancak testler başarısız olursa, bu seçenek mevcut olup olmadığına bakılmaksızın stdoutları yazdırılır.


10
--nocaptureSeçeneği geçmekten bahsettiniz cargo test, ancak kargo bu bayrağı benim için tanımıyor (rustup.sh'dan en son geceyi kullanarak). Çalışması gerektiğinden emin misiniz?
Jim Garrison

42
@JimGarrison, aslında, bununla ilgili bir sorun var. Bu arada kullanabilirsiniz cargo test -- --nocapture, çalışması gerekir.
Vladimir Matveev

4
Teşekkürler! bu soru ile ilgisiz, ama bu da nasıl cargo test [--] --benchçalışacağımı anlamama yardımcı oldu !
Jim Garrison

6
@Nashenas, seçenek denir nocapture, değil no-capture.
Vladimir Matveev

1
Herkes Windows Visual Studio kodu hata ayıklama sırasında yazdırma nasıl anladınız mı? Aşağıdaki görev açılan kabuğa yazdırılmaz: "kargo testi - no-run - --nocapture" hata ayıklayıcısı. Her iki şekilde de bir fark yaratmıyor gibi görünse de çalışmayan argümanının kullanımına dikkat edin. Tüm gördüğüm "1 test çalışıyor". Garip takımlar.
David

75

TL; DR

$ cargo test -- --nocapture

Aşağıdaki kodla:

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

Ardından aşağıdakileri çalıştırın:

 $ cargo test -- --nocapture

Ve görmelisin

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-captureArtık çalışmıyor. Aşağıdaki hatayı alıyorum:thread '<main>' panicked at '"Unrecognized option: \'no-capture\'."', ../src/libtest/lib.rs:249
Nashenas

Ben bu konuda acaba github.com/rust-lang/cargo/issues/1377 sorundur?
superlogical

5
Önceki yorumlarda belirtildiği gibi, seçenek --nocapturedeğil --no-capture. Ancak, çoğu komut satırı konvansiyonuna rastlamak tamamen bariz bir hatadır. Bu seçeneği sadece pas 1.1'de (kargo 0.2.0) bu cevapta açıklandığı gibi kullandım ve tam olarak ilan edildiği gibi çalıştı.
Glenn McAllister

10

Çıktıları dahil etmek println!()ve test sonuçları için renkleri tutmak için colorve nocaptureişaretlerini kullanın cargo test.

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

(kargo versiyonu: 0.13.0 gecelik)


6

Test sırasında standart çıktı gösterilmez. Test fakat kısa mesaj kullanmayın assert!, assert_eq!ve fail!bunun yerine. Rust'un birim test sistemi bunları anlayabilir ancak metin mesajlarını anlayamaz.

Bir şey yanlış gitse bile yazdığınız sınav geçecektir. Bakalım neden:

read_to_endimzası fn read_to_end(&mut self) -> IoResult<Vec<u8>>

IoResultBaşarıyı veya hatayı belirtmek için bir döndürür . Bu sadece Resulthata değeri bir olan bir tür def IoError. Bir hatanın nasıl ele alınması gerektiğine karar vermek size kalmıştır. Bu durumda, görevin başarısız olmasını istiyoruz unwrap.Result .

Bu çalışacak:

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

unwrap Yine de aşırı kullanılmamalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.