क्या होगा अगर आपके यूनिट टेस्ट झूठ बोल रहे हैं?
\nआपने सौ यूनिट टेस्ट लिखे हैं। वे पास हो जाते हैं। C++ कोड बिल्कुल सही दिखता है। लेकिन जब आप प्रोडक्शन में एप्लिकेशन चलाते हैं, तो यह 100500वें अनुरोध पर segmentation fault के साथ क्रैश हो जाता है। परिचित दर्द है ना?
\nपारंपरिक यूनिट टेस्ट केवल वही जांचते हैं जो आपने स्वयं सोचा है। वे उन परिदृश्यों के प्रति अंधे होते हैं जो आपके दिमाग में नहीं आए। प्रॉपर्टी-आधारित परीक्षण (या property-based testing, PBT) इस समस्या को मौलिक रूप से हल करता है: यह विशिष्ट उदाहरणों की जांच नहीं करता, बल्कि लाखों यादृच्छिक इनपुट डेटा के लिए आपके कोड के गुणों (properties) को सिद्ध करता है।
\nइस लेख में, हम RapidCheck लाइब्रेरी के साथ C++ में प्रॉपर्टी-आधारित परीक्षण को लागू करने का तरीका समझेंगे, और देखेंगे कि यह उन बग्स को कैसे पकड़ता है जिन्हें सामान्य यूनिट टेस्ट छोड़ देते हैं। क्या आप अपने कोड को वास्तव में परेशान करने के लिए तैयार हैं? चलिए शुरू करते हैं।
\n\nप्रॉपर्टी-आधारित परीक्षण: 30 सेकंड में दर्शन
\nकल्पना करें कि आप एक सॉर्टिंग फ़ंक्शन का परीक्षण कर रहे हैं। सामान्य टेस्ट: sort([3,1,2]) == [1,2,3]। ठीक है, एक मामले की जाँच की।
प्रॉपर्टी-आधारित दृष्टिकोण: "पूर्णांकों की किसी भी सूची के लिए, सॉर्ट करने के बाद लंबाई नहीं बदलती, तत्व आरोही क्रम में होते हैं, और मूल सूची का प्रत्येक तत्व सॉर्ट की गई सूची में मौजूद होता है"। फ्रेमवर्क सैकड़ों यादृच्छिक सूचियाँ (खाली, डुप्लिकेट वाली, ऋणात्मक संख्याओं वाली) उत्पन्न करता है और इन गुणों की जाँच करता है।
\nमुख्य विचार: आप इनवेरिएंट (properties) का वर्णन करते हैं जो हमेशा सत्य होने चाहिए, न कि विशिष्ट इनपुट और आउटपुट।
\n\nC++ में PBT कब विशेष रूप से उपयोगी है?
\n- \n
- एल्गोरिदम और डेटा संरचनाएँ (सॉर्टिंग, खोज, ग्राफ) \n
- पार्सर और सीरियलाइज़र (एन्कोडिंग/डिकोडिंग) \n
- गणितीय फ़ंक्शन (व्युत्क्रम संक्रियाएँ, मानों की श्रेणियाँ) \n
- मेमोरी प्रबंधन (लीक, डबल फ्री) \n
- कोई भी कोड जहाँ स्पष्ट इनवेरिएंट हों \n
RapidCheck: आपका नया सबसे अच्छा दोस्त
\nC++ में PBT के लिए कई लाइब्रेरी हैं, लेकिन RapidCheck सबसे परिपक्व और सुविधाजनक है। यह Haskell लाइब्रेरी QuickCheck से प्रेरित है और Google Test तथा Catch2 के साथ शानदार ढंग से एकीकृत होती है।
\nइंस्टॉलेशन सरल है: यह header-only लाइब्रेरी है, बस include/rapidcheck से फ़ाइलों को अपने प्रोजेक्ट में कॉपी करें। या Conan/vcpkg का उपयोग करें।
पहला टेस्ट: व्युत्क्रम संक्रिया का गुण
\nमान लीजिए, हमारे पास एक फ़ंक्शन है जो स्ट्रिंग को base64 में एन्कोड करता है और वापस डिकोड करता है। कौन सा गुण स्पष्ट है? "एन्कोडिंग के बाद डिकोडिंग मूल स्ट्रिंग लौटाता है"।
\n#include <rapidcheck.h>\n#include <string>\n\nstd::string encode_base64(const std::string& input);\nstd::string decode_base64(const std::string& input);\n\nint main() {\n rc::check("एन्कोडिंग के बाद डिकोडिंग मूल स्ट्रिंग लौटाता है",\n [](const std::string& original) {\n // स्ट्रिंग जनरेटर पहले से बिल्ट-इन है\n auto encoded = encode_base64(original);\n auto decoded = decode_base64(encoded);\n RC_ASSERT(decoded == original);\n });\n return 0;\n}\n\nयहाँ क्या हो रहा है? RapidCheck यादृच्छिक स्ट्रिंग्स (खाली, Unicode वाली, शून्य बाइट्स वाली) उत्पन्न करता है। प्रत्येक के लिए, यह गुण की जाँच करता है। यदि यह एक प्रतिउदाहरण पाता है — न्यूनतम (shrinking) जो अभी भी टेस्ट को तोड़ता है। यह सोना है: आपको केवल "बग है" नहीं, बल्कि एक विशिष्ट पुनरुत्पादनीय मामला मिलता है।
\n\nउन्नत गुण: समानता से अधिक
\nमोनोटोनिसिटी और इडेम्पोटेंसी
\nremove_duplicates फ़ंक्शन के लिए:
- \n
- इडेम्पोटेंसी: यदि दो बार लागू किया जाए, तो परिणाम नहीं बदलता। \n
- क्रम महत्वपूर्ण नहीं है: परिणामी सूची में मूल सूची के समान तत्व होते हैं, लेकिन डुप्लिकेट के बिना। \n
#include <vector>\n#include <algo