مقدمة: لماذا يعتبر اختبار C++ أساس الكود الموثوق
\nالتطوير بلغة C++ دائمًا ما يكون عملًا بمسؤولية عالية. تمنحك اللغة تحكمًا كاملاً في الذاكرة والأداء، لكن ثمن الخطأ قد يكون كارثيًا: من تسرب الذاكرة إلى انهيار النظام بأكمله. ولهذا السبب، فإن اختبار C++ ليس خيارًا، بل مرحلة إلزامية في تطوير أي مشروع جاد.
\nفي هذه المقالة، سنستعرض ثلاثة مستويات رئيسية للاختبار: الوحدة (unit)، التكامل (integration)، وe2e (الشامل). ستتعرف على الفروق بينها، والأدوات التي يجب استخدامها، وكيفية كتابة اختبارات C++ بشكل صحيح. ستكون المادة مفيدة لكل من المبتدئين والمطورين ذوي الخبرة الذين يرغبون في تنظيم معرفتهم.
\n\n1. اختبار الوحدة في C++: اختبار "اللبنات" الأساسية للبرنامج
\nاختبارات الوحدة (أو الاختبارات النمطية) تختبر أصغر وحدة في الكود — عادةً دالة فردية أو طريقة في كلاس. هدفها الرئيسي: عزل المكون والتأكد من أنه يعمل بشكل صحيح بمعزل عن التبعيات الخارجية.
\n\n1.1. أدوات اختبار الوحدة في C++
\nفي سوق C++، توجد عدة أطر ناضجة. إليك الأكثر شيوعًا:
\n- \n
- Google Test (GTest) — المعيار الفعلي. ماكرو قوي، دعم للاختبارات المعلمية، وكائنات وهمية (عبر Google Mock). \n
- Catch2 — خفيف، حديث، مع بناء جملة ممتاز. مناسب للمشاريع الصغيرة. \n
- Boost.Test — جزء من مكتبة Boost. ضخم ولكنه غني بالوظائف. \n
سنستخدم Google Test باعتباره الخيار الأكثر شيوعًا.
\n\n1.2. مثال على اختبار وحدة في C++ (Google Test)
\nلنفترض أن لدينا دالة بسيطة لحساب المضروب:
\n// math_utils.h\n#pragma once\nint factorial(int n);\n// math_utils.cpp\n#include "math_utils.h"\nint factorial(int n) {\n if (n < 0) return -1; // خطأ: رقم سالب\n if (n == 0) return 1;\n return n * factorial(n - 1);\n}\nالآن سنكتب اختبار وحدة باستخدام Google Test:
\n// test_math_utils.cpp\n#include <gtest/gtest.h>\n#include "math_utils.h"\n\nTEST(FactorialTest, HandlesZeroInput) {\n EXPECT_EQ(factorial(0), 1);\n}\n\nTEST(FactorialTest, HandlesPositiveInput) {\n EXPECT_EQ(factorial(5), 120);\n}\n\nTEST(FactorialTest, HandlesNegativeInput) {\n EXPECT_EQ(factorial(-1), -1);\n}\n\nint main(int argc, char **argv) {\n ::testing::InitGoogleTest(&argc, argv);\n return RUN_ALL_TESTS();\n}\nنشغل الاختبارات — ونرى الضوء الأخضر. إذا كان هناك خطأ في الدالة (مثلاً، factorial(5) يُرجع 119)، سيفشل الاختبار وسنعرف بالمشكلة فورًا.
1.3. أفضل الممارسات لاختبارات الوحدة
\n- \n
- العزل: استخدم الكائنات الوهمية (Mock) لاستبدال التبعيات الخارجية (قاعدة بيانات، شبكة، نظام ملفات). \n
- فحص واحد لكل اختبار: يجب أن يختبر كل
TESTسلوكًا واحدًا. \n - أسماء واضحة:
HandlesZeroInputأفضل منTest1. \n - تغطية الحالات الحدية: الصفر، الأرقام السالبة، القيم القصوى. \n
2. اختبار التكامل (Integration Testing): التحقق من التفاعل
\nتختبر اختبارات التكامل كيفية عمل الوحدات المختلفة للنظام معًا. على عكس اختبارات الوحدة، لا نقوم بعزل المكونات هنا — بل نتحقق من الروابط الحقيقية (مثل استدعاء دالة من كلاس يستخدم كلاسًا آخر).
\n\n2.1. متى نحتاج إلى اختبار التكامل؟
\n- \n
- عندما تتبادل وحدتان البيانات (مثل محلل + مدقق). \n
- عند العمل مع موارد خارجية: قاعدة بيانات، ملفات، مآخذ شبكة. \n
- بعد دمج عدة مكونات تم اختبارها وحدويًا. \n