परिचय: रस्ट में परीक्षण उबाऊ क्यों नहीं है
\n\nयदि आपने कभी Python या JavaScript में कोड के लिए परीक्षण लिखे हैं, तो आप निश्चित रूप से ऐसी स्थिति का सामना किया होगा: आपकी विधि बाहरी API को कॉल करती है, डिस्क से फ़ाइल पढ़ती है या डेटाबेस तक पहुँचती है। वास्तविक वातावरण में ऐसे परीक्षण चलाना दर्दनाक है। वे धीमे, अविश्वसनीय (अगर API डाउन हो जाए?) और वातावरण सेटअप की आवश्यकता होती है।
\n\nरस्ट में स्थिति अलग नहीं है। बस रस्ट एक सिस्टम भाषा है, और यहाँ परीक्षण तेज़, विश्वसनीय और नियतात्मक होने चाहिए। इसी के लिए मॉक-ऑब्जेक्ट और फिक्स्चर की आवश्यकता है।
\n\nइस लेख में, हम देखेंगे कि रस्ट में ऐसे परीक्षण कैसे लिखें जो बाहरी दुनिया पर निर्भर न हों। आप सीखेंगे कि निर्भरताओं को कैसे बदलें, परीक्षणों के लिए डेटा कैसे तैयार करें और इसे सुंदर तरीके से करें। चलिए शुरू करते हैं!
\n\nमॉक-ऑब्जेक्ट और फिक्स्चर क्या हैं?
\n\nमॉक-ऑब्जेक्ट (मॉक)
\nमॉक-ऑब्जेक्ट सिस्टम के वास्तविक घटक का अनुकरण है। आप एक ऐसी वस्तु बनाते हैं जो परीक्षण के लिए आवश्यकतानुसार व्यवहार करती है: निर्धारित मान लौटाती है, त्रुटियाँ फेंकती है या जाँचती है कि इसकी विधियाँ सही तर्कों के साथ बुलाई गईं।
\n\nकल्पना करें कि आपके पास ईमेल भेजने की एक सेवा है। परीक्षण में आप वास्तव में ईमेल नहीं भेजना चाहते - आप एक मॉक का उपयोग करते हैं जो केवल यह जाँचता है कि सेवा सही पते और टेक्स्ट के साथ बुलाई गई।
\n\nफिक्स्चर (fixtures)
\nफिक्स्चर तैयार डेटा या स्थिति हैं जो परीक्षण को निष्पादित करने के लिए आवश्यक हैं। उदाहरण के लिए, परीक्षण डेटाबेस, कॉन्फ़िगरेशन फ़ाइल, पूर्व-स्थापित संरचनाएँ। रस्ट में, फिक्स्चर अक्सर सामान्य फ़ंक्शन के माध्यम से कार्यान्वित किए जाते हैं जो तैयार ऑब्जेक्ट लौटाते हैं।
\n\nएक साथ, मॉक और फिक्स्चर आपको परीक्षण वातावरण पर पूर्ण नियंत्रण देते हैं। आप केवल अपने तर्क का परीक्षण करते हैं, बाहरी सेवाओं के काम का नहीं।
\n\nरस्ट में परीक्षण के मूल सिद्धांत
\n\nमॉक में गोता लगाने से पहले, आइए याद करें कि रस्ट में परीक्षण कैसे काम करते हैं। एक सामान्य मॉड्यूल परीक्षण इस तरह दिखता है:
\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn test_addition() {\n assert_eq!(2 + 2, 4);\n }\n}\n\n\nसब कुछ सरल है। लेकिन जब आपका कोड बाहरी संसाधनों (फ़ाइलें, HTTP अनुरोध, डेटाबेस) पर निर्भर होने लगता है, तो समस्याएँ उत्पन्न होती हैं। समाधान - निर्भरताओं को उलटना और Dependency Injection (निर्भरता इंजेक्शन) पैटर्न का उपयोग करना है।
\n\nव्यावहारिक उदाहरण: डेटा लोडिंग सेवा
\n\nमान लीजिए, हमारे पास एक संरचना DataLoader है जो बाहरी API से डेटा लोड करती है और उसे संसाधित करती है। हम वास्तविक API को कॉल किए बिना प्रसंस्करण का परीक्षण करना चाहते हैं।
पहले डेटा स्रोत के लिए एक ट्रेट (इंटरफ़ेस) परिभाषित करें:
\n\npub trait DataSource {\n fn fetch_data(&self) -> Result<String, String>;\n}\n\n\nअब वास्तविक स्रोत को लागू करें जो HTTP अनुरोध करता है (सरलीकृत):
\n\npub struct RealDataSource {\n pub url: String,\n}\n\nimpl DataSource for RealDataSource {\n fn fetch_data(&self) -> Result<String, String> {\n // यहाँ वास्तविक HTTP अनुरोध होगा\n Ok(format!("{} से डेटा", self.url))\n }\n}\n\n\nऔर वह सेवा जो इस स्रोत का उपयोग करती है:
\n\npub struct DataLoader<T: DataSource> {\n source: T,\n}\n\nimpl<T: DataSource> DataLoader<T> {\n pub fn new(source: T) -> Self {\n DataLoader { source }\n }\n\n pub fn load_and_process(&self) -> Result<String, String> {\n let raw_data = self.source.fetch_data()?;\n // कुछ प्रसंस्करण\n Ok(format!("संसाधित: {}", raw_data))\n }\n}\n\n\nध्यान दें: DataLoader DataSource के विशिष्ट कार्यान्वयन पर निर्भर नहीं है। यह किसी भी प्रकार के साथ काम करता है जो इस ट्रेट को लागू करता है। यह परीक्षण क्षमता की कुंजी है।
मैन्युअल रूप से मॉक-ऑब्जेक्ट बनाना
\n\nसबसे सरल तरीका एक परीक्षण संरचना बनाना है