C++ का उन्नत परीक्षण: यूनिट-टेस्ट से end-to-end तक
\nआधुनिक C++ विकास में, कोड की गुणवत्ता न केवल उसके प्रदर्शन से, बल्कि विश्वसनीयता से भी निर्धारित होती है। उन्नत परीक्षण सरल जाँचों से कहीं आगे जाता है — यह एक आर्किटेक्चरल दृष्टिकोण है, जिसमें यूनिट टेस्ट, इंटीग्रेशन टेस्ट और end-to-end (e2e) टेस्ट शामिल हैं। इस लेख में, हम Google Test, Google Mock और स्वयं के फ्रेमवर्क का उपयोग करके C++ प्रोजेक्ट्स के लिए परीक्षण पिरामिड को सही ढंग से कैसे बनाया जाए, इस पर चर्चा करेंगे।
\n\n1. यूनिट-परीक्षण: अलगाव और मॉक
\nयूनिट टेस्ट अलग-अलग मॉड्यूल (फंक्शन, क्लास) को अलगाव में जाँचते हैं। उन्नत स्तर पर, मुख्य कार्य निर्भरताओं को सही ढंग से मॉक करना सीखना है। Google Mock का उपयोग करके एक उदाहरण देखें।
\n\nमान लीजिए, हमारे पास एक क्लास DatabaseConnector है जो बाहरी API पर निर्भर करती है। हम वास्तविक डेटाबेस का उपयोग किए बिना डेटा प्रोसेसिंग लॉजिक का परीक्षण करना चाहते हैं।
#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\nclass DatabaseInterface {\npublic:\n virtual ~DatabaseInterface() = default;\n virtual std::string fetchData(int id) = 0;\n};\n\nclass MockDatabase : public DatabaseInterface {\npublic:\n MOCK_METHOD(std::string, fetchData, (int id), (override));\n};\n\nclass DataProcessor {\n DatabaseInterface& db;\npublic:\n explicit DataProcessor(DatabaseInterface& db) : db(db) {}\n std::string process(int id) {\n auto raw = db.fetchData(id);\n if (raw.empty()) return "EMPTY";\n return "PROCESSED: " + raw;\n }\n};\n\nTEST(DataProcessorTest, ProcessWithValidData) {\n MockDatabase mockDb;\n EXPECT_CALL(mockDb, fetchData(42))\n .WillOnce(testing::Return("Hello"));\n DataProcessor processor(mockDb);\n EXPECT_EQ(processor.process(42), "PROCESSED: Hello");\n}\n\nMOCK_METHOD का उपयोग निर्भरताओं के व्यवहार को सटीक रूप से नियंत्रित करने की अनुमति देता है। अप्रत्याशित कॉल को पकड़ने के लिए strict mocks (NiceMock या StrictMock के माध्यम से) को याद रखना महत्वपूर्ण है।
2. इंटीग्रेशन परीक्षण: अंतःक्रियाओं का परीक्षण
\nइंटीग्रेशन टेस्ट जाँचते हैं कि मॉड्यूल एक साथ कैसे काम करते हैं। C++ में, इसमें अक्सर फ़ाइल सिस्टम, नेटवर्क प्रोटोकॉल या डेटाबेस के साथ काम करने का परीक्षण शामिल होता है। उन्नत दृष्टिकोण test fixtures और parameterized tests का उपयोग करना है।
\n\nउदाहरण: हम क्लास FileManager का परीक्षण कर रहे हैं, जो फ़ाइलों को पढ़ता और लिखता है। अस्थायी निर्देशिकाओं का उपयोग करें।
class FileManagerTest : public ::testing::Test {\nprotected:\n std::filesystem::path tempDir;\n void SetUp() override {\n tempDir = std::filesystem::temp_directory_path() / "test_files";\n std::filesystem::create_directories(tempDir);\n }\n void TearDown() override {\n std::filesystem::remove_all(tempDir);\n }\n};\n\nTEST_F(FileManagerTest, WriteAndReadFile) {\n FileManager fm(tempDir.string());\n fm.write("test.txt", "data");\n auto content = fm.read("test.txt");\n EXPECT_EQ(content, "data");\n}\n\nपैरामीटराइज़्ड टेस्ट के लिए, TEST_P का उपयोग INSTANTIATE_TEST_SUITE_P के साथ करें। यह एक ही परीक्षण को विभिन्न इनपुट डेटा के साथ चलाने की अनुमति देता है।
class MathTest : public ::testing::TestWithParam<std::tuple<int, int, int>> {};\nTEST_P(MathTest, Add) {\n auto [a, b, expected] = GetParam();\n EXPECT_EQ(add(a, b), expected);\n}\nINSTANTIATE_TEST_SUITE_P(AddTests, MathTest,\n ::testing::Values(\n std::make_tuple(1, 1, 2),\n std::make_tuple(-1, 1, 0),\n std::make_tuple(0, 0, 0)\n ));\n\n3. End-to-End परीक्षण: पूर्ण चक्र की जाँच
\nE2e टेस्ट अंतिम उपयोगकर्ता के व्यवहार का अनुकरण करते हैं। C++ अनुप्रयोगों के लिए, इसका अर्थ पूर्ण बाइनरी चलाना, उसके आउटपुट की जाँच करना या API के माध्यम से इंटरैक्शन करना हो सकता है। उन्नत स्तर