Testlerin Nasıl Çalıştırıldığını Kontrol Etme

Tıpkı cargo run'un kodunuzu derlemesi ve ardından ortaya çıkan ikili dosyayı çalıştırması gibi, cargo test de kodunuzu test modunda derler ve ortaya çıkan test ikili dosyasını çalıştırır. cargo test tarafından üretilen ikilinin varsayılan davranışı, tüm testleri paralel olarak çalıştırmak ve test çalıştırmaları sırasında üretilen çıktıyı yakalamak, çıktının görüntülenmesini önlemek ve test sonuçlarıyla ilgili çıktıyı okumayı kolaylaştırmaktır. Bununla birlikte, bu varsayılan davranışı değiştirmek için komut satırı seçenekleri belirleyebilirsiniz.

Bazı komut satırı seçenekleri cargo test'e, bazıları ise elde edilen test ikilisine gider. Bu iki tür argümanı ayırmak için, cargo test'e giden argümanları ve ardından ayırıcıyı -- ve ardından test ikilisine gidenleri listelersiniz. cargo test --help komutunu çalıştırdığınızda cargo test ile kullanabileceğiniz seçenekler görüntülenir ve cargo test -- --help komutunu çalıştırdığınızda ayırıcıdan sonra kullanabileceğiniz seçenekler görüntülenir.

Testleri Paralel veya Ardışık Olarak Çalıştırma

Birden fazla test çalıştırdığınızda, varsayılan olarak iş parçacıkları kullanılarak paralel olarak çalışırlar, yani daha hızlı çalışırlar ve daha hızlı geri bildirim alırsınız. Testler aynı anda çalıştığından, testlerinizin birbirlerine veya geçerli çalışma dizini veya ortam değişkenleri gibi paylaşılan bir ortam da dahil olmak üzere herhangi bir paylaşılan duruma bağlı olmadığından emin olmalısınız.

Örneğin, testlerinizin her birinin diskte test-output.txt adında bir dosya oluşturan ve bu dosyaya bazı veriler yazan bir kod çalıştırdığını varsayalım. Ardından her test bu dosyadaki verileri okur ve dosyanın her testte farklı olan belirli bir değer içerdiğini iddia eder. Testler aynı anda çalıştığından, bir testin dosyayı yazması ve okuması arasında geçen sürede bir test dosyanın üzerine yazabilir. Bu durumda ikinci test, kod hatalı olduğu için değil, testler paralel olarak çalışırken birbirine karıştığı için başarısız olacaktır. Bir çözüm, her testin farklı bir dosyaya yazdığından emin olmaktır; başka bir çözüm ise testleri teker teker çalıştırmaktır.

Testleri paralel olarak çalıştırmak istemiyorsanız veya kullanılan iş parçacığı sayısı üzerinde daha ayrıntılı kontrol istiyorsanız, --test-threads bayrağını ve kullanmak istediğiniz iş parçacığı sayısını test ikilisine gönderebilirsiniz.

Aşağıdaki örneğe bir göz atın:

$ cargo test -- --test-threads=1

Test iş parçacığı sayısını 1 olarak ayarladık ve programa herhangi bir paralellik kullanmamasını söyledik. Testleri tek bir iş parçacığı kullanarak çalıştırmak, paralel olarak çalıştırmaktan daha uzun sürecektir, ancak testler durumu paylaşırlarsa birbirlerini etkilemeyeceklerdir.

Fonksiyon Çıktısını Gösterme

Varsayılan olarak, bir test geçerse, Rust'ın test kütüphanesi standart çıktıya yazdırılan her şeyi yakalar. Örneğin, bir testte println! komutunu çağırırsak ve test geçerse, uçbirimde println! çıktısını görmeyiz; yalnızca testin geçtiğini gösteren satırı görürüz. Bir test başarısız olursa, başarısız mesajının geri kalanıyla birlikte standart çıktıya ne yazdırıldıysa onu görürüz.

Örnek olarak, Liste 11-10'da parametresinin değerini yazdıran ve 10 döndüren saçma bir fonksiyonun yanı sıra başarılı olan bir test ve başarısız olan bir test vardır.

Dosya adı: src/lib.rs

fn prints_and_returns_10(a: i32) -> i32 {
    println!("I got the value {}", a);
    10
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn this_test_will_pass() {
        let value = prints_and_returns_10(4);
        assert_eq!(10, value);
    }

    #[test]
    fn this_test_will_fail() {
        let value = prints_and_returns_10(8);
        assert_eq!(5, value);
    }
}

Liste 11-10: println! çağrısı yapan bir fonksiyon için testler

Bu testleri cargo test ile çalıştırdığımızda aşağıdaki çıktıyı göreceğiz:

$ cargo test
   Compiling silly-function v0.1.0 (file:///projects/silly-function)
    Finished test [unoptimized + debuginfo] target(s) in 0.58s
     Running unittests (target/debug/deps/silly_function-160869f38cff9166)

running 2 tests
test tests::this_test_will_fail ... FAILED
test tests::this_test_will_pass ... ok

failures:

---- tests::this_test_will_fail stdout ----
I got the value 8
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `5`,
 right: `10`', src/lib.rs:19:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::this_test_will_fail

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass '--lib'

Bu çıktının hiçbir yerinde I got the value 4 ifadesini görmediğimize dikkat edin; bu, geçen test çalıştırıldığında yazdırılan değerdir. Bu çıktı yakalanmıştır. Başarısız olan testin çıktısı, I got the value 8, test özeti çıktısının test başarısızlığının nedenini de gösteren bölümünde görünür.

Geçen testler için de yazdırılan değerleri görmek istiyorsak, Rust'a --show-output ile başarılı testlerin çıktısını da en sonunda göstermesini söyleyebiliriz.

$ cargo test -- --show-output

Liste 11-10'daki testleri --show-output bayrağı ile tekrar çalıştırdığımızda aşağıdaki çıktıyı görüyoruz:

$ cargo test -- --show-output
   Compiling silly-function v0.1.0 (file:///projects/silly-function)
    Finished test [unoptimized + debuginfo] target(s) in 0.60s
     Running unittests (target/debug/deps/silly_function-160869f38cff9166)

running 2 tests
test tests::this_test_will_fail ... FAILED
test tests::this_test_will_pass ... ok

successes:

---- tests::this_test_will_pass stdout ----
I got the value 4


successes:
    tests::this_test_will_pass

failures:

---- tests::this_test_will_fail stdout ----
I got the value 8
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `5`,
 right: `10`', src/lib.rs:19:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::this_test_will_fail

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass '--lib'

Bir Test Alt Kümesini Ada Göre Çalıştırma

Bazen tam bir test paketi çalıştırmak uzun zaman alabilir. Belirli bir alandaki kod üzerinde çalışıyorsanız, yalnızca o kodla ilgili testleri çalıştırmak isteyebilirsiniz. Çalıştırmak istediğiniz test(ler)in adını veya adlarını cargo test'e argüman olarak ileterek hangi testlerin çalıştırılacağını seçebilirsiniz.

Testlerin bir alt kümesinin nasıl çalıştırılacağını göstermek için, önce Liste 11-11'de gösterildiği gibi add_two fonksiyonumuz için üç test oluşturacağız ve hangilerinin çalıştırılacağını seçeceğiz.

Dosya adı: src/lib.rs

pub fn add_two(a: i32) -> i32 {
    a + 2
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn add_two_and_two() {
        assert_eq!(4, add_two(2));
    }

    #[test]
    fn add_three_and_two() {
        assert_eq!(5, add_two(3));
    }

    #[test]
    fn one_hundred() {
        assert_eq!(102, add_two(100));
    }
}

Liste 11-11: Üç farklı isimle üç test

Testleri daha önce gördüğümüz gibi herhangi bir argüman geçmeden çalıştırırsak, tüm testler paralel olarak çalışacaktır:

$ cargo test
   Compiling adder v0.1.0 (file:///projects/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.62s
     Running unittests (target/debug/deps/adder-92948b65e88960b4)

running 3 tests
test tests::add_three_and_two ... ok
test tests::add_two_and_two ... ok
test tests::one_hundred ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests adder

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Tekdüze Testleri Çalıştırma

Yalnızca bu testi çalıştırmak için herhangi bir test fonksiyonunun adını cargo test'e geçirebiliriz:

$ cargo test one_hundred
   Compiling adder v0.1.0 (file:///projects/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.69s
     Running unittests (target/debug/deps/adder-92948b65e88960b4)

running 1 test
test tests::one_hundred ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.00s

Sadece one_hundred isimli test çalıştı; diğer iki test bu isimle eşleşmedi. Test çıktısı, sonunda filtrelenen 2'yi görüntüleyerek çalışmayan daha fazla testimiz olduğunu bilmemizi sağlar.

Bu şekilde birden fazla testin adını belirtemeyiz; yalnızca cargo test'e verilen ilk değer kullanılır. Ancak birden fazla test çalıştırmanın bir yolu var.

Birden Fazla Test Çalıştırmak için Filtreleme

Bir test adının bir kısmını belirtebiliriz ve adı bu değerle eşleşen herhangi bir test çalıştırılır. Örneğin,testlerimizden ikisinin adı add içerdiğinden, bu ikisini cargo test add komutuyla çalıştırabiliriz:

$ cargo test add
   Compiling adder v0.1.0 (file:///projects/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.61s
     Running unittests (target/debug/deps/adder-92948b65e88960b4)

running 2 tests
test tests::add_three_and_two ... ok
test tests::add_two_and_two ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s

Bu komut, adında add olan tüm testleri çalıştırır ve one_hundred adlı testi filtreler. Ayrıca, bir testin göründüğü modülün testin adının bir parçası haline geldiğini unutmayın, bu nedenle modülün adına göre filtreleme yaparak bir modüldeki tüm testleri çalıştırabiliriz.

Özel Olarak İstenmedikçe Bazı Testleri Yok Sayma

Bazen belirli birkaç testin yürütülmesi çok zaman alıcı olabilir, bu nedenle cargo test'in çoğu çalıştırması sırasında bunları hariç tutmak isteyebilirsiniz. Çalıştırmak istediğiniz tüm testleri argüman olarak listelemek yerine, zaman alan testleri burada gösterildiği gibi dışlamak için ignore niteliğini kullanarak açıklama ekleyebilirsiniz:

Dosya adı: src/lib.rs

#[test]
fn it_works() {
    assert_eq!(2 + 2, 4);
}

#[test]
#[ignore]
fn expensive_test() {
    // code that takes an hour to run
}

#[test]'ten sonra, hariç tutmak istediğimiz teste #[ignore] satırını ekliyoruz. Testlerimizi çalıştırdığımızda it_works çalışıyor, ancak expensive_test çalışmıyor:

$ cargo test
   Compiling adder v0.1.0 (file:///projects/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.60s
     Running unittests (target/debug/deps/adder-92948b65e88960b4)

running 2 tests
test expensive_test ... ignored
test it_works ... ok

test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests adder

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

expensive_test fonksiyonu ignored olarak listeleniyor. Yalnızca göz ardı edilen testleri çalıştırmak istiyorsak, cargo test -- --ignored'u kullanabiliriz:

$ cargo test -- --ignored
   Compiling adder v0.1.0 (file:///projects/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.61s
     Running unittests (target/debug/deps/adder-92948b65e88960b4)

running 1 test
test expensive_test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s

   Doc-tests adder

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Hangi testlerin çalışacağını kontrol ederek, cargo test sonuçlarınızın hızlı olmasını sağlayabilirsiniz. Yok sayılan testlerin sonuçlarını kontrol etmenin mantıklı olduğu bir noktaya geldiğinizde ve sonuçları beklemek için zamanınız olduğunda, bunun yerine cargo test -- --ignored komutunu çalıştırabilirsiniz. Yok sayılsın ya da sayılmasın tüm testleri çalıştırmak istiyorsanız, cargo test -- --include-ignored komutunu çalıştırabilirsiniz.