100% कवरेज का विरोधाभास — या आपके टेस्ट क्यों झूठ बोल सकते हैं
\n\nआपने Rust में परफेक्ट कोड लिखा। कंपाइलर खुश है, clippy चुप है, टेस्ट हरे रंग की लहर में पास हो रहे हैं, और कवरेज रिपोर्ट गर्व से बताती है: 100% लाइनें कवर हैं। क्या आप राहत की सांस ले सकते हैं? नहीं। Rust में म्यूटेशन टेस्टिंग वह तकनीक है जो आपको दिखाएगी कि आपके टेस्ट शायद हवा की रक्षा कर रहे हैं, तर्क की नहीं।
\n\nकल्पना करें: आप गलती से किसी महत्वपूर्ण फंक्शन में + को - में बदल देते हैं। टेस्ट अभी भी हरे हैं? बधाई हो, आपको एक म्यूटेंट मिल गया — एक दोष जो आपके कोड में रहता है, लेकिन टेस्ट इसे नोटिस नहीं करते। इस लेख में, हम देखेंगे कि कैसे Rust में म्यूटेशन टेस्टिंग ऐसे ब्लाइंड स्पॉट खोजने में मदद करती है, और इसे एक वास्तविक प्रोजेक्ट में लागू करेंगे।
म्यूटेशन टेस्टिंग क्या है (और Rust इसके लिए आदर्श क्यों है)
\n\nMutation testing (या म्यूटेशन टेस्टिंग) टेस्ट की गुणवत्ता का मूल्यांकन करने की एक विधि है, जिसमें स्रोत कोड में छोटे कृत्रिम परिवर्तन (म्यूटेशन) किए जाते हैं, और फिर टेस्ट चलाए जाते हैं। यदि टेस्ट म्यूटेटेड कोड पर फेल नहीं होते हैं — तो इसका मतलब है कि म्यूटेंट बच गया। जितने अधिक जीवित म्यूटेंट होंगे, आपके टेस्ट उतने ही खराब होंगे।
\n\nRust एक ऐसी भाषा है जो अपने आप कंपाइलेशन के समय त्रुटियों की पूरी श्रेणियों को पकड़ लेती है: race conditions, null pointers, use-after-free। लेकिन Rust में म्यूटेशन टेस्टिंग विशेष रूप से तार्किक त्रुटियों पर लक्षित है — वह जो कंपाइलर नहीं देखता। और यह Rust को एक आदर्श मंच बनाता है: आप पहले से ही 70% सामान्य बग से सुरक्षित हैं, और म्यूटेशन टेस्टिंग शेष 30% को खत्म कर देती है।
\n\nRust कोड में म्यूटेशन कैसा दिखता है
\n\nसामान्य म्यूटेशन में शामिल हैं:
\n- \n
- ऑपरेटरों का परिवर्तन:
a + b→a - b\n - शर्तों का उलटना:
if x > 5→if x < 5\n - कॉन्स्टेंट का प्रतिस्थापन:
let n = 42→let n = 0\n - फंक्शन कॉल को हटाना:
process(data)→ खाली कॉल \n - इटरेशन सीमाओं का परिवर्तन:
0..n→0..=n\n
यदि ऐसे म्यूटेशन के बाद कम से कम एक टेस्ट फेल नहीं होता — तो इसका मतलब है कि आपने यह टेस्ट लिखने में समय बर्बाद किया। यह वह जाँच नहीं कर रहा जो उसे करनी चाहिए।
\n\nRust में म्यूटेशन टेस्टिंग के लिए टूल्स: cargo-mutants
\n\nआज, Rust में म्यूटेशन टेस्टिंग के लिए मुख्य टूल cargo-mutants है। यह परिपक्व है, सक्रिय रूप से समर्थित है, और पढ़ने योग्य रिपोर्ट देता है। इंस्टॉलेशन सरल है:
cargo install cargo-mutants\n\n\nइसके बाद, बस चलाएँ:
\n\ncargo mutants\n\n\nऔर टूल स्वचालित रूप से आपके कोड में सभी म्यूटेशन ढूंढेगा, टेस्ट चलाएगा, और रंग संकेत के साथ HTML रिपोर्ट देगा: हरा — मारे गए म्यूटेंट (टेस्ट ने काम किया), लाल — जीवित (समस्या)।
\n\nरेडार पर विकल्प
\n- \n
- mutagen — पुराना, लेकिन अभी भी काम करने वाला टूल। कम म्यूटेशन, छोटे प्रोजेक्ट पर तेज़ काम करता है। \n
- cargo-insta — पूरी तरह से म्यूटेशन टेस्टिंग नहीं, लेकिन करीब है: टेस्ट स्नैपशॉट में बदलावों को दृश्य रूप से जाँचने में मदद करता है। \n
गंभीर काम के लिए, मैं cargo-mutants की सलाह देता हूँ — यह गति और विश्लेषण की गहराई के बीच सबसे अच्छा संतुलन देता है।
व्यावहारिक उदाहरण: डिस्काउंट कैलकुलेटर का परीक्षण
\n\nमान लीजिए, हमारे पास Rust में ऑनलाइन स्टोर के लिए डिस्काउंट गणना मॉड्यूल है:
\n\n// src/discount.rs\n\npub fn calculate_discount(price: f64, customer_age: u32) -> f64 {\n let mut discount = 0.0;\n\n // वरिष्ठ नागरिकों (65 से अधिक) के लिए 10% छूट\n if customer_age > 65 {\n discount += 0.1;\n }\n\n // 1000 रुपये से अधिक की खरीदारी पर अतिरिक्त 5% छूट\n if price > 1000.0 {\n discount += 0.05;\n }\n\n // अधिकतम छूट 30% से अधिक नहीं\n if discount > 0.30 {\n discount = 0.30;\n