Yazılım kodunun test edilmesi, geliştirme endüstrisindeki en eski ve en önemli süreçlerden biridir. Ancak birçok dilde test kitaplıkları ayrı olarak sağlanır ve testlerin ana koda entegrasyonu opak veya kullanışsız olabilir. Rust, ilk sürümlerinden itibaren, açık modüler test desteği ile tasarlanmıştır.
Birçok geleneksel dilde testler ayrı bir yerde bulunur veya belirli çerçeveler ve derleyiciler yapılandırması gerektirir. Bu, ortak geliştirmeyi zorlaştırır, ana mantık ile testler arasındaki senkronizasyon riskini artırır ve entegrasyon ve modüler test yapmayı zorlaştırır.
Rust, test sistemini doğrudan dil seviyesinde entegre eder: #[cfg(test)] modülü, #[test] direktifi ve cargo test aracı, testleri kaynak kodu içinde oluşturma, çalıştırma ve kontrol etme imkanı sağlar. Bu, kod ile onu kontrol eden testler arasında sıkı bir bağ kurar, testleri çalıştırmanın kolaylığını ve CI/CD süreçlerinin otomasyonunu garanti eder.
Kod örneği:
// tests automatically compiled and run by `cargo test` #[cfg(test)] mod tests { use super::*; #[test] fn it_adds_two() { assert_eq!(2 + 2, 4); } }
Anahtar özellikler:
cargo test) tüm bulunan testleri başlatır.#[cfg(test)] özel niteliği kullanımı, testlerin yayın derlemesine dahil edilmemesini sağlar.Testlerde kararsız veya özel işlevleri kullanmak mümkün mü ve nasıl yapılır?
Evet, mümkündür. #[cfg(test)] olarak tanımlanan test modülünün içinde, testler yalnızca genel değil, aynı zamanda mevcut modülün özel API'sini de görmektedir. Bu, uygulama detaylarını doğrudan test etmeniz anlamına gelir. Ancak, başka bir modülden yalnızca genel arayüz aracılığıyla erişebilirsiniz.
Örnek:
fn private_internal(x: i32) -> i32 { x + 1 } #[cfg(test)] mod tests { use super::*; #[test] fn test_private() { assert_eq!(private_internal(41), 42); } }
Farklı modüller arasında aynı adı taşıyan testler çakışır mı?
Hayır, test adları yalnızca kendi modülleri içinde görünür. Farklı modüllerin testleri aynı isimde olabilir, çünkü derleyici bunları tam yol (namespace) ile ayırt eder.
Örnek:
mod a { #[cfg(test)] mod tests { #[test] fn basic() {} } } mod b { #[cfg(test)] mod tests { #[test] fn basic() {} } }
Bireysel bir testi veya test setinin bir kısmını çalıştırmak mümkün mü?
Evet, test isminin filtrelenmesiyle: cargo test test_adı. Bu, büyük setlerin hata ayıklaması için kullanışlıdır.
Örnek:
cargo test only_this_test
Geliştirici testleri ayrı bir projeye taşıdı, özel işlevlere erişimi olmadı ve dizin yapısı farklıydı. Ana kütüphanedeki değişiklikler nedeniyle testler hızla geride kaldı ve güncelliğini yitirdi.
Artılar: Test etmeyi izole edebilirsiniz, test modüllerinin yayın derlemesine kazara dahil olmasını önleyebilirsiniz.
Eksiler: Senkronizasyon kaybı, dahili detayları test etme imkanı kaybı, yüksek sürdürülebilirlik ve testlerin güncelliği riski.
Testler, ana mantıkla tam olarak aynı modüllerde yazılır, küçük atomik test vakaları özel ve genel API'yi test eder. Yeni başlayan, testler aracılığıyla modülün çalışmasına hızlıca aşina olur.
Artılar: Maksimum senkronizasyon desteği, şeffaflık, hızlandırılmış yerel test etme, test odaklı geliştirmeye uygunluk.
Eksiler: Kaynak dosyalarındaki kod satırı sayısının artması, çok sayıda test ile karmaşıklığın potansiyel olarak artması.