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.