اختبار PHP: الوحدة، التكامل، E2E من الألف إلى الياء

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

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

ابدأ الدورة

مقدمة: لماذا نحتاج إلى الاختبار في PHP؟

\n\n

التطوير في PHP بدون اختبار يشبه بناء منزل بدون أساس. عاجلاً أم آجلاً، سينهار التطبيق وسيرى المستخدمون "الشاشة البيضاء للموت". اختبار الكود ليس ترفاً، بل ضرورة لأي مشروع جاد. فهو يتيح:

\n
    \n
  • اكتشاف الأخطاء في المراحل المبكرة — قبل وصول الكود إلى بيئة الإنتاج.
  • \n
  • تبسيط إعادة الهيكلة — يمكنك تغيير البنية بثقة، مع العلم أن الاختبارات ستكتشف أي تراجع.
  • \n
  • إنشاء كود موثق ذاتياً — الاختبارات تعمل كتوثيق حي لكيفية عمل النظام.
  • \n
  • زيادة ثقة الفريق — كل commit جديد يخضع لفحص تلقائي.
  • \n
\n\n

في PHP، هناك ثلاثة مستويات رئيسية للاختبار: Unit (الوحدة)، Integration (التكامل)، وE2E (الشامل). في هذه المقالة، سنشرح كل مستوى منهم بأمثلة عملية، من assert-ات بسيطة إلى اختبارات متصفح كاملة.

\n\n

1. اختبار الوحدة: اختبار "اللبنات الأساسية" للتطبيق

\n\n

ما هو اختبار الوحدة؟

\n

اختبار الوحدة يتحقق من عمل كتلة صغيرة واحدة من الكود — عادةً دالة أو method واحدة — في عزلة تامة عن التبعيات الخارجية (قاعدة البيانات، API، نظام الملفات).

\n\n

الأدوات المستخدمة في PHP

\n
    \n
  • PHPUnit — المعيار الفعلي. يُستخدم في Laravel وSymfony والعديد من أنظمة إدارة المحتوى.
  • \n
  • Pest — بديل حديث بتركيبة أكثر إيجازاً، مبني على PHPUnit.
  • \n
\n\n

مثال: اختبار حاسبة الخصم

\n

لنفترض أن لدينا كلاس بسيط DiscountCalculator:

\n\n
<?php\n\nclass DiscountCalculator\n{\n    public function calculate(float $price, float $percent): float\n    {\n        if ($percent < 0 || $percent > 100) {\n            throw new \\InvalidArgumentException('يجب أن تكون النسبة المئوية بين 0 و 100');\n        }\n        return $price - ($price * $percent / 100);\n    }\n}\n
\n\n

الآن سنكتب اختبار وحدة باستخدام PHPUnit:

\n\n
<?php\n\nuse PHPUnit\\Framework\\TestCase;\n\nclass DiscountCalculatorTest extends TestCase\n{\n    private DiscountCalculator $calculator;\n\n    protected function setUp(): void\n    {\n        $this->calculator = new DiscountCalculator();\n    }\n\n    public function testCalculateWithZeroPercent(): void\n    {\n        $result = $this->calculator->calculate(100, 0);\n        $this->assertEquals(100, $result);\n    }\n\n    public function testCalculateWithFiftyPercent(): void\n    {\n        $result = $this->calculator->calculate(200, 50);\n        $this->assertEquals(100, $result);\n    }\n\n    public function testCalculateThrowsExceptionOnInvalidPercent(): void\n    {\n        $this->expectException(\\InvalidArgumentException::class);\n        $this->calculator->calculate(100, 150);\n    }\n}\n
\n\n

النقاط الرئيسية:

\n
    \n
  • كل method يختبر سيناريو واحد فقط.
  • \n
  • لا نصل إلى قاعدة البيانات أو الخدمات الخارجية.
  • \n
  • نستخدم setUp() لتهيئة الكائنات المشتركة.
  • \n
\n\n

أفضل ممارسات اختبار الوحدة

\n
    \n
  • اتبع مبدأ FIRST: سريع (Fast)، معزول (Isolated)، قابل للتكرار (Repeatable)، ذاتي التحقق (Self-validating)، في الوقت المناسب (Timely).
  • \n
  • سمِّ الاختبارات كـ "test_الإجراء_النتيجةالمتوقعة".
  • \n
  • تجنب المنطق في الاختبارات — لا if/switch/حلقات.
  • \n
\n\n

2. اختبار التكامل: التحقق من تفاعل المكونات

\n\n

ما الفرق عن اختبار الوحدة؟

\n

اختبارات التكامل تتحقق من كيفية عمل الأجزاء المختلفة من النظام معاً. على سبيل المثال، كيف يتفاعل service الخاص بك مع قاعدة بيانات حقيقية، أو cache، أو API خارجي.

\n\n

مثال: اختبار repository مع قاعدة بيانات (Laravel + SQLite)

\n

لنفترض أن لدينا <

المدونات

توصيات الكتب