مقدمة: لماذا بدون كائنات المحاكاة وتركيبات الاختبار تكون الاختبارات يانصيبًا
\n\nتخيل أنك تكتب كودًا لمركبة فضائية. وظيفتك تحسب المسار، وتستدعي وحدة التحكم في المحرك. كيف تتحقق من صحة المسار دون تشغيل المحرك الحقيقي؟ في العالم الحقيقي، هذه كارثة. في عالم C++، هذه مهمة كائنات المحاكاة (mock) وتركيبات الاختبار (fixtures).
\n\nإذا سبق لك كتابة اختبارات وحدات بلغة C++، فبالتأكيد واجهت مشاكل: فشل الاختبار بسبب الشبكة، أو قاعدة البيانات، أو نظام الملفات. أو ربما تنفق 10 أسطر لإعداد البيانات لكل تحقق. هل هذا مألوف؟ إذن هذه المقالة لك.
\n\nسنشرح كيف تساعد كائنات المحاكاة في C++ في عزل الكود عن العالم الخارجي، وكيف تساعد تركيبات الاختبار في إعادة استخدام إعدادات الاختبار. لا حشو، فقط كود وتطبيق عملي. لنبدأ!
\n\nما هي كائنات المحاكاة ولماذا نحتاجها في C++
\n\nكائن المحاكاة (Mock) هو بديل لكائن حقيقي يحاكي سلوكه. تقول للمحاكي: "عند استدعاء الدالة getData()، أعد 42". وهو يطيع ويعيد 42، دون الاتصال بقاعدة البيانات أو API أو ملف.
\n\nفي C++، تعتبر كائنات المحاكاة مهمة بشكل خاص لأن اللغة لا تغفر الأخطاء. إذا كان صفك يعتمد على الشبكة، وسقطت الشبكة - سيفشل الاختبار، على الرغم من أن كودك مثالي. تحل كائنات المحاكاة هذه المشكلة: فهي تعزل الكود المختبر.
\n\nالسيناريوهات الرئيسية لاستخدام كائنات المحاكاة في C++:
\n- \n
- الخدمات الخارجية (قواعد البيانات، REST API، الملفات). \n
- الحسابات المعقدة التي تبطئ الاختبارات (التشفير، التصيير). \n
- الدوال غير الحتمية (rand(), time()). \n
- التحقق من التفاعل: هل تم استدعاء الدالة، كم مرة، وبأي وسائط. \n
لإنشاء كائنات المحاكاة في C++، المعيار الفعلي هو مكتبة Google Mock (gmock)، والتي تأتي مع Google Test. ولكن يمكنك أيضًا كتابة كائنات المحاكاة يدويًا - للمشاريع الصغيرة، هذا أسهل.
\n\nتركيبات الاختبار: تجهيز المسرح للاختبار
\n\nتركيبة الاختبار (Test Fixture) هي مجموعة من الكائنات والبيانات اللازمة لتنفيذ الاختبار. بدلاً من كتابة كل مرة:
\n\nMyClass obj;\nobj.init("data");\nobj.connect();\n\n...تقوم بنقل هذا إلى تركيبة الاختبار. يدعم Google Test تركيبات الاختبار من خلال الوراثة من ::testing::Test. هذا ليس مجرد راحة - إنها أفضل ممارسة لاختبار C++.
تحل تركيبات الاختبار ثلاث مهام:
\n- \n
- إعادة استخدام الكود - إعداد مرة واحدة، واستخدامه في جميع الاختبارات. \n
- نظافة الاختبارات - يبدأ كل اختبار من نفس الحالة. \n
- التنظيف التلقائي - إذا كنت بحاجة لتحرير الموارد، يتم ذلك في مدمر تركيبة الاختبار. \n
والآن دعنا نجمع كائنات المحاكاة وتركيبات الاختبار في مثال واحد.
\n\nكتابة اختبار مع كائن محاكاة وتركيبة اختبار: مثال عملي
\n\nلنفترض أن لدينا صفًا WeatherReporter يحصل على بيانات الطقس عبر API. نريد اختبار الدالة getTemperature() دون الاتصال بالخادم الحقيقي.
الخطوة 1. تعريف الواجهة
\n\nلاستبدال كائن محاكاة، نحتاج إلى صف مجرد. هذه نقطة أساسية: تعمل كائنات المحاكاة من خلال تعدد الأشكال.
\n\n// weather_api.h\nclass WeatherAPI {\npublic:\n virtual ~WeatherAPI() = default;\n virtual double getTemperature(const std::string& city) = 0;\n virtual bool isAvailable() = 0;\n};\n\nالخطوة 2. تنفيذ كائن المحاكاة باستخدام Google Mock
\n\n// mock_weather_api.h\n#include <gmock/gmock.h>\n#include "weather_api.h"\n\nclass MockWeatherAPI : public WeatherAPI {\npublic:\n MOCK_METHOD(double, getTemperature, (const std::string& city), (override));\n MOCK_METHOD(bool, isAvailable, (), (override