परिचय: Rust में परीक्षण विश्वसनीय कोड का आधार क्यों है
Rust एक सिस्टम प्रोग्रामिंग भाषा है जो अपनी मेमोरी सुरक्षा और प्रदर्शन के लिए प्रसिद्ध है। हालांकि, सबसे सख्त कंपाइलर भी यह गारंटी नहीं देता कि आपका प्रोग्राम वही करता है जो उसे करना चाहिए। यहीं पर परीक्षण की भूमिका आती है। Rust में परीक्षणों के लिए अंतर्निहित समर्थन आधुनिक भाषाओं में सबसे अच्छा है। आप तृतीय-पक्ष लाइब्रेरी को शामिल किए बिना यूनिट-परीक्षण (मॉड्यूलर), इंटीग्रेशन-परीक्षण (एकीकरण) और e2e-परीक्षण (एंड-टू-एंड) लिख सकते हैं।
इस लेख में हम व्यावहारिक उदाहरणों के साथ परीक्षण के तीनों स्तरों का विश्लेषण करेंगे। आप सीखेंगे कि परीक्षण कैसे लिखें, उन्हें cargo test के साथ कैसे चलाएं, और बड़े प्रोजेक्ट्स के लिए परीक्षण बुनियादी ढांचा कैसे व्यवस्थित करें।
1. Rust में यूनिट-परीक्षण: फ़ंक्शन और मॉड्यूल का परीक्षण
यूनिट-परीक्षण अलग-अलग फ़ंक्शन या विधियों के काम को अलगाव में जांचते हैं। Rust में यूनिट-परीक्षणों को स्रोत कोड फ़ाइल में ही, #[cfg(test)] एनोटेशन वाले tests मॉड्यूल के अंदर रखने की प्रथा है। यह परीक्षणों को मॉड्यूल के निजी फ़ंक्शन तक पहुंच प्रदान करता है।
1.1. पहला यूनिट-परीक्षण
आइए गणनाओं के लिए एक सरल लाइब्रेरी बनाएं और उसके लिए परीक्षण लिखें।
// src/lib.rspub fn add(a: i32, b: i32) -> i32 { a + b}
pub fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("शून्य से भाग")) } else { Ok(a / b) }}
#[cfg(test)]mod tests { use super::*;
#[test] fn test_add() { assert_eq!(add(2, 3), 5); }
#[test] fn test_divide_success() { let result = divide(10.0, 2.0).unwrap(); assert_eq!(result, 5.0); }
#[test] fn test_divide_by_zero() { let result = divide(10.0, 0.0); assert!(result.is_err()); assert_eq!(result.unwrap_err(), "शून्य से भाग"); }}परीक्षणों को cargo test कमांड से चलाएं। यदि सभी परीक्षण पास हो जाते हैं तो आपको हरे निशान दिखाई देंगे।
1.2. परीक्षणों के गुण
#[test]— इंगित करता है कि फ़ंक्शन एक परीक्षण है।#[should_panic]— परीक्षण को पास माना जाता है यदि फ़ंक्शन पैनिक उत्पन्न करता है।#[ignore]— अस्थायी रूप से परीक्षण को अक्षम करता है।
#[test]#[should_panic(expected = "पैनिक संदेश")]fn test_panic() { panic!("पैनिक संदेश");}
#[test]#[ignore = "बग #42 ठीक होने तक परीक्षण अक्षम"]fn test_expensive() { // लंबा परीक्षण}2. इंटीग्रेशन-परीक्षण: घटकों के बीच अंतःक्रिया की जांच
इंटीग्रेशन-परीक्षण कई मॉड्यूल या बाहरी निर्भरताओं के एक साथ काम करने की जांच करते हैं। Rust में इन्हें प्रोजेक्ट की जड़ स्तर पर एक अलग निर्देशिका tests/ में रखा जाता है। इस फ़ोल्डर में प्रत्येक फ़ाइल एक अलग परीक्षण क्रेट है, जो आपकी लाइब्रेरी के केवल सार्वजनिक API को देखता है।
2.1. इंटीग्रेशन परीक्षणों की संरचना
एक tests/ फ़ोल्डर और फ़ाइल tests/integration_test.rs बनाएं:
// tests/integration_test.rsuse my_crate::add; // आपके क्रेट का नाम
#[test]fn test_add_integration() { // जांचें कि फ़ंक्शन लाइब्रेरी के भाग के रूप में काम करता है let result = add(10, 20); assert_eq!(result, 30);}
#[test]fn test_divide_integration() { // कई कॉल के साथ परीक्षण let a = 100.0; let b = 4.0; let result = my_crate::divide(a, b).unwrap(); assert!(result > 0.0); assert_eq!(result, 25.0);}2.2. इंटीग्रेशन परीक्षणों के लिए सामान्य मॉड्यूल
यदि आपको इंटीग्रेशन परीक्षणों के बीच कोड का पुन: उपयोग करना है, तो एक फ़ाइल tests/common/mod.rs बनाएं। इसे परीक्षण फ़ाइल के रूप में नहीं माना जाएगा, लेकिन आप इसे अन्य परीक्षणों से आयात कर सकेंगे।
// tests/common/mod.rspub fn setu