اختبار في C++: نظرة عامة على الأطر والأدوات (Google Test, Catch2, doctest)

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

اختبار في C++: الأطر والأدوات



جودة كود C++ هي عامل حاسم لموثوقية البرمجيات. على عكس اللغات ذات الذاكرة المُدارة، يمكن أن تؤدي الأخطاء في C++ إلى أعطال خطيرة، وتسريبات للذاكرة، وسلوك غير محدد. يسمح نظام اختبار الوحدة (unit-testing) باكتشاف العيوب في المراحل المبكرة، ويسهل إعادة الهيكلة، ويوثق سلوك الدوال. في هذه المقالة، سنستعرض ثلاثة أطر شائعة لاختبار C++: Google Test وCatch2 وdoctest، بالإضافة إلى أدوات دمجها في عملية التطوير.



لماذا نحتاج الاختبار في C++؟

  • الأمان أثناء إعادة الهيكلة: الاختبارات تنبه فورًا عن الانتكاسات.
  • التوثيق: الاختبارات القابلة للقراءة تعمل كأمثلة حية لاستخدام API.
  • التكامل مع CI: تشغيل تلقائي للاختبارات مع كل commit.
  • اكتشاف السلوك غير المحدد: اختبارات باستخدام أدوات التعقيم (AddressSanitizer, UndefinedBehaviorSanitizer).


1. Google Test (GTest)

الإطار الأكثر شيوعًا من Google. يدعم نمط xUnit، ومجموعة غنية من وحدات الماكرو للتأكيدات (assertions)، وتسجيل تلقائي للاختبارات، والمحاكاة (عبر Google Mock)، والاختبارات المُعلمة.



التثبيت (عبر CMake FetchContent)

# CMakeLists.txtinclude(FetchContent)FetchContent_Declare(  googletest  GIT_REPOSITORY https://github.com/google/googletest.git  GIT_TAG release-1.12.1)FetchContent_MakeAvailable(googletest)

add_executable(my_tests test.cpp)target_link_libraries(my_tests GTest::gtest_main)


مثال اختبار

#include <gtest/gtest.h>

int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n - 1);}

TEST(FactorialTest, HandlesZeroInput) { EXPECT_EQ(factorial(0), 1);}

TEST(FactorialTest, HandlesPositiveInput) { EXPECT_EQ(factorial(5), 120); EXPECT_GT(factorial(3), 5);}

int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}
  • TEST() — ماكرو لتعريف حالة اختبار.
  • EXPECT_EQ — التحقق من المساواة (غير قاتل).
  • ASSERT_* — تحقق قاتل (يوقف الاختبار عند الفشل).


2. Catch2

إطار حديث يركز على سهولة القراءة والبساطة. يدعم نمط BDD (Given-When-Then)، والأقسام (تقسيم الاختبارات إلى سيناريوهات متداخلة)، وتوليد بيانات عشوائية. لا يتطلب وراثة من فئات أساسية.



التثبيت (ملف رأس واحد أو عبر vcpkg)

# vcpkgvcpkg install catch2

# CMakefind_package(Catch2 REQUIRED)target_link_libraries(my_tests Catch2::Catch2)


مثال اختبار

#define CATCH_CONFIG_MAIN#include <catch2/catch.hpp>

int add(int a, int b) { return a + b; }

TEST_CASE("Addition works", "[math]") { REQUIRE(add(2, 2) == 4); CHECK(add(-1, 1) == 0);

SECTION("With zero") { REQUIRE(add(0, 5) == 5); }}

TEST_CASE("String concatenation", "[string]") { std::string result = std::string("Hello ") + "World"; CHECK(result == "Hello World");}
  • TEST_CASE — تعريف اختبار باسم ووسوم.
  • REQUIRE — تحقق قاتل.
  • CHECK — تحقق غير قاتل.
  • SECTION — سيناريو متداخل (كل قسم يُشغل من حالة مشتركة).


3. Doctest

بديل خفيف وسريع. مستوحى من Catch2، لكنه يُترجم أسرع بمقدار 2-5 مرات. مصمم للمشاريع التي تهم فيها سرعة البناء. يدعم ملف الرأس فقط (header-only)، ووحدات الماكرو CHECK وREQUIRE، والإخراج بتنسيق XML.



التثبيت (he

توصيات