परिचय: C++ प्रोजेक्ट्स के लिए परीक्षण क्यों महत्वपूर्ण है
C++ कोड का परीक्षण केवल एक औपचारिकता नहीं है, बल्कि एक मौलिक अभ्यास है जो सॉफ्टवेयर की स्थिरता, सुरक्षा और रखरखाव सुनिश्चित करता है। इंटरप्रेटेड भाषाओं के विपरीत, जहां त्रुटि तुरंत प्रकट हो सकती है, C++ में बग अक्सर बिल्ड या विशिष्ट परिस्थितियों में निष्पादन तक छिपे रहते हैं। छूटी हुई मेमोरी लीक, अनिर्धारित व्यवहार या पॉइंटर्स के साथ गलत संचालन घातक विफलताओं का कारण बन सकता है।
आधुनिक विकास उद्योग परीक्षण के तीन मुख्य स्तरों को अलग करता है: Unit (मॉड्यूलर), Integration (एकीकरण) और E2E (एंड-टू-एंड)। उनमें से प्रत्येक अपनी समस्या का समाधान करता है और साथ में वे एक "परीक्षण पिरामिड" बनाते हैं, जो प्रोडक्शन में जाने से पहले 90% तक त्रुटियों को पकड़ने की अनुमति देता है।
इस लेख में, हम लोकप्रिय फ्रेमवर्क Google Test और Catch2 का उपयोग करके C++ पर व्यावहारिक उदाहरणों के साथ प्रत्येक प्रकार के परीक्षण का विश्लेषण करेंगे, और उनके उपयोग के सर्वोत्तम अभ्यासों पर चर्चा करेंगे।
1. Unit-परीक्षण: परमाणु मॉड्यूल की जाँच
Unit-परीक्षण सबसे निचला और सबसे तेज़ स्तर है। वे शेष सिस्टम से अलग व्यक्तिगत फ़ंक्शन, क्लास या विधियों की जाँच करते हैं। उद्देश्य यह सुनिश्चित करना है कि कोड का प्रत्येक "बिल्डिंग ब्लॉक" सही ढंग से काम करता है।
Google Test के साथ Unit-परीक्षण का उदाहरण
एक सरल गणितीय फ़ंक्शन पर विचार करें:
// math_utils.h#pragma once
namespace MathUtils { int add(int a, int b); int divide(int a, int b);}// math_utils.cpp#include "math_utils.h"
namespace MathUtils { int add(int a, int b) { return a + b; }
int divide(int a, int b) { if (b == 0) { throw std::invalid_argument("Division by zero"); } return a / b; }}अब Google Test का उपयोग करके unit-परीक्षण लिखें:
// test_math_utils.cpp#include <gtest/gtest.h>#include "math_utils.h"
TEST(MathUtilsTest, AddPositiveNumbers) { EXPECT_EQ(MathUtils::add(2, 3), 5); EXPECT_EQ(MathUtils::add(0, 0), 0);}
TEST(MathUtilsTest, AddNegativeNumbers) { EXPECT_EQ(MathUtils::add(-1, -1), -2); EXPECT_EQ(MathUtils::add(-5, 3), -2);}
TEST(MathUtilsTest, DivideNormal) { EXPECT_EQ(MathUtils::divide(10, 2), 5); EXPECT_EQ(MathUtils::divide(7, 3), 2); // पूर्णांक विभाजन}
TEST(MathUtilsTest, DivideByZeroThrows) { EXPECT_THROW(MathUtils::divide(5, 0), std::invalid_argument);}Mock-ऑब्जेक्ट्स का उपयोग
मॉड्यूल को अलग करने के लिए अक्सर निर्भरताओं को बदलने की आवश्यकता होती है। Google Mock (Google Test का भाग) आपको स्टब बनाने की अनुमति देता है:
// database_interface.hclass DatabaseInterface {public: virtual ~DatabaseInterface() = default; virtual bool save(const std::string& data) = 0;};
// user_service.cppclass UserService { DatabaseInterface& db;public: explicit UserService(DatabaseInterface& db) : db(db) {} bool registerUser(const std::string& name) { return db.save("user:" + name); }};
// test_user_service.cpp#include <gmock/gmock.h>
class MockDatabase : public DatabaseInterface {public: MOCK_METHOD(bool, save, (const std::string&), (override));};
TEST(UserServiceTest, RegisterUserCallsDb) { MockDatabase mockDb; EXPECT_CALL(mockDb, save("user:Alice")).WillOnce(testing::Return(true));
UserService service(mockDb); EXPECT_TRUE(service.registerUser("Alice"));}लाभ: निष्पादन की गति (मिलीसेकंड), त्रुटियों का सटीक स्थानीयकरण, बाहरी निर्भरताओं के बिना चलाने की क्षमता।
नुकसान: वास्तविक घटकों के बीच बातचीत की जाँच नहीं करते।
2. एकीकरण परीक्षण: घटकों के कनेक्शन की जाँच
Integration-परीक्षण जाँचते हैं कि कई मॉड्यूल एक साथ कैसे काम करते हैं।
```