परिचय: टेस्ट पास हो जाते हैं, लेकिन बग रह जाते हैं?
\n\nएक स्थिति की कल्पना करें: आपने Go में एक मॉड्यूल लिखा, इसे go test -cover द्वारा 95% यूनिट टेस्ट से कवर किया, सभी टेस्ट हरे हैं। आपको विश्वास है कि कोड पूरी तरह से काम करता है। लेकिन प्रोडक्शन में एक बग निकल आता है। परिचित लगता है?
समस्या यह है कि कोड कवरेज (code coverage) मीट्रिक केवल उन पंक्तियों की संख्या है जो निष्पादित की गईं। यह नहीं बताती कि टेस्ट वास्तव में क्या जाँच रहे हैं। आपके पास 100% कवरेज हो सकता है, लेकिन कभी यह जाँच नहीं की कि फंक्शन सही मान लौटाता है, न कि केवल पैनिक नहीं होता।
\n\nयहाँ पर Go में म्यूटेशन टेस्टिंग (mutation testing) आता है — एक ऐसी तकनीक जो कृत्रिम रूप से आपके कोड में त्रुटियाँ डालती है और देखती है कि क्या टेस्ट उन्हें पकड़ पाते हैं। यदि टेस्ट म्यूटेटेड कोड पर फेल नहीं होते — तो आपके टेस्ट बेकार हैं।
\n\nइस लेख में, हम समझेंगे कि Go में म्यूटेशन टेस्टिंग क्या है, इसे कैसे सेट अप करें, और यह उन प्रोजेक्ट्स के लिए क्यों आवश्यक है जहाँ विश्वसनीयता महत्वपूर्ण है। चलिए शुरू करते हैं!
\n\nम्यूटेशन टेस्टिंग क्या है?
\n\nम्यूटेशन टेस्टिंग टेस्ट की गुणवत्ता का मूल्यांकन करने की एक विधि है, जिसमें प्रोग्राम में छोटे बदलाव (म्यूटेशन) किए जाते हैं जो डेवलपर की सामान्य गलतियों का अनुकरण करते हैं। फिर टेस्ट चलाए जाते हैं। यदि कम से कम एक टेस्ट फेल होता है — म्यूटेशन "मारा गया", टेस्ट काम कर रहा है। यदि सभी टेस्ट पास हो जाते हैं — म्यूटेशन "बच गया", और यह एक लाल झंडा है: आपके टेस्ट में एक छेद है।
\n\nGo में, म्यूटेशन टेस्टिंग को अक्सर mutation testing golang कहा जाता है, और यह विशेष रूप से बिज़नेस लॉजिक, वैलिडेटर, पार्सर और अन्य महत्वपूर्ण घटकों की जाँच के लिए उपयोगी है।
\n\nम्यूटेशन का उदाहरण
\n\nमान लीजिए, आपके पास एक सरल फंक्शन है:
\n\nfunc IsEven(n int) bool {\n return n%2 == 0\n}\n\nएक सामान्य म्यूटेशन — == को != से बदलना:
func IsEven(n int) bool {\n return n%2 != 0\n}\n\nयदि आपका टेस्ट केवल यह जाँचता है कि IsEven(2) फेल नहीं होता, लेकिन यह नहीं जाँचता कि परिणाम true है, तो म्यूटेशन बच जाएगा। टेस्ट पास हो जाएगा, जबकि फंक्शन अब उल्टा काम कर रहा है।
सिर्फ कोड कवरेज पर्याप्त क्यों नहीं है?
\n\nGo में कई डेवलपर go test -cover पर भरोसा करने के आदी हैं। यह एक उपयोगी मीट्रिक है, लेकिन यह भ्रामक है। एक उदाहरण देखें:
func Divide(a, b int) (int, error) {\n if b == 0 {\n return 0, errors.New("division by zero")\n }\n return a / b, nil\n}\n\nटेस्ट:
\n\nfunc TestDivide(t *testing.T) {\n result, err := Divide(10, 2)\n if err != nil {\n t.Fatal(err)\n }\n if result != 5 {\n t.Errorf("expected 5, got %d", result)\n }\n}\n\nकवरेज? 100% — सभी पंक्तियाँ निष्पादित हुईं। लेकिन क्या होगा अगर कोई गलती से a / b को a * b से बदल दे? टेस्ट इसे नोटिस नहीं करेगा, क्योंकि 10 * 2 = 20, जबकि हमें 5 की उम्मीद थी। क्या टेस्ट फेल होगा? नहीं, अगर हम सटीक मान की जाँच नहीं कर रहे हैं।
Go में म्यूटेशन टेस्टिंग तुरंत इस समस्या को उजागर करेगी, गुणा के साथ एक म्यूटेंट बनाकर और यह जाँच कर कि क्या टेस्ट फेल होता है।
\n\nGo में म्यूटेशन टेस्टिंग के लिए उपकरण
\n\nमुख्य उपकरण go-mutesting है। यह एक लोकप्रिय लाइब्रेरी है जो स्वचालित रूप से म्यूटेशन बनाती है और टेस्ट चलाती है। इंस्टॉलेशन:
\n\ngo get github.com/zimmski/go-mutesting/cmd/go-mutesting\n\nइसके विकल्प भी हैं, जैसे कि "Go Test It" कंपनी का mutesting, लेकिन go-mutesting डी-फैक्टो मानक है।
कैसे चलाएँ
\n\nबेसिक रन:
\n\ngo-mutesting ./...\n\nयह कमांड प्रोजेक्ट में सभी _test.go फ़ाइलें ढूँढ़ेगा और जाँच करेगा कि कौन से म्यूटेशन बचते हैं। परिणाम विस्तृत रिपोर्ट के साथ कंसोल पर आउटपुट होता है।
व्यावहारिक उदाहरण: Go पर म्यूटेशन टेस्टिंग
\n\nआइए जोड़ और