اختبار التكامل C++ مع Docker: المستوى المتقدم
\n\nاختبار التكامل هو مرحلة حاسمة في تطوير C++، خاصة في البنى الخدمية المصغرة الحديثة. غالبًا ما تؤدي الأساليب التقليدية، حيث يتم تنفيذ الاختبارات في بيئة المطور، إلى أخطاء بسبب الاختلافات في البيئة وإصدارات المكتبات والتكوينات. يقدم Docker حلاً أنيقًا: العزل الكامل، قابلية التكرار، والأتمتة. في هذه المقالة، سنستعرض تقنيات متقدمة لاختبار التكامل لتطبيقات C++ باستخدام Docker، بما في ذلك إدارة التبعيات، تشغيل الاختبارات المتوازي، والتكامل مع CI/CD.
\n\n1. بنية بيئة الاختبار على Docker
\n\nالخطوة الأولى نحو اختبار تكامل موثوق هي البنية الصحيحة لبيئة Docker. بدلاً من حاوية واحدة متجانسة، نقوم بإنشاء تركيبة من الخدمات، كل منها مسؤول عن مهمته الخاصة: الخدمة قيد الاختبار، قاعدة البيانات، ذاكرة التخزين المؤقت، قوائم الرسائل، إلخ.
\n\nلننظر إلى مثال لخدمة مصغرة C++ تستخدم PostgreSQL و Redis. ملف docker-compose.test.yml:
version: '3.8'\n\nservices:\n postgres_test:\n image: postgres:15-alpine\n environment:\n POSTGRES_USER: test_user\n POSTGRES_PASSWORD: test_pass\n POSTGRES_DB: test_db\n healthcheck:\n test: ["CMD-SHELL", "pg_isready -U test_user -d test_db"]\n interval: 2s\n timeout: 5s\n retries: 10\n\n redis_test:\n image: redis:7-alpine\n healthcheck:\n test: ["CMD", "redis-cli", "ping"]\n interval: 2s\n timeout: 5s\n retries: 10\n\n cpp_service_test:\n build:\n context: .\n dockerfile: Dockerfile.test\n depends_on:\n postgres_test:\n condition: service_healthy\n redis_test:\n condition: service_healthy\n environment:\n - DB_HOST=postgres_test\n - DB_PORT=5432\n - REDIS_HOST=redis_test\n - REDIS_PORT=6379\n - TEST_MODE=1\n volumes:\n - ./test_results:/app/test_results\n command: ["./run_integration_tests"]\n\nالنقاط الرئيسية:
\n- \n
- فحوصات الصحة تضمن أن الاختبارات تبدأ فقط بعد أن تصبح التبعيات جاهزة. \n
- شبكة منفصلة (يتم إنشاؤها تلقائيًا) تعزل بيئة الاختبار عن الإنتاج. \n
- وحدة تخزين للنتائج تسمح بسحب تقارير الاختبار بعد الانتهاء. \n
2. كتابة اختبارات التكامل بلغة C++ مع مراعاة Docker
\n\nيجب أن تكون اختباراتك جاهزة للعمل في بيئة محتواة. هذا يعني أن تكوين الاتصال بالخدمات الخارجية يجب أن يتم تعيينه من خلال متغيرات البيئة، وليس ترميزه بشكل ثابت.
\n\nمثال لاختبار باستخدام Google Test و libpqxx لـ PostgreSQL:
\n\n#include <gtest/gtest.h>\n#include <pqxx/pqxx>\n#include <cstdlib>\n\nclass DatabaseIntegrationTest : public ::testing::Test {\nprotected:\n std::unique_ptr<pqxx::connection> conn;\n\n void SetUp() override {\n const char* db_host = std::getenv("DB_HOST");\n const char* db_port = std::getenv("DB_PORT");\n const char* db_user = std::getenv("POSTGRES_USER");\n const char* db_pass = std::getenv("POSTGRES_PASSWORD");\n const char* db_name = std::getenv("POSTGRES_DB");\n\n ASSERT_NE(db_host, nullptr) << "DB_HOST not set";\n ASSERT_NE(db_port, nullptr) << "DB_PORT not set";\n\n std::string conn_str = "host=" + std::string(db_host) +\n " port=" + std::string(db_port) +\n " user=" + std::string(db_user ? db_user : "test_user") +\n " password=" + std::string(db_pass ? db_pass : "test_pass") +\n " dbname=" + std::string(db_name ? db_name : "test_db");\n\n try {\n conn = std::make_unique<pqxx::connect