مقدمة: لماذا يستحق كودك الاحترام (والاختبارات)
\n\nتخيل: تكتب كودًا يعمل بشكل مثالي، كل شيء على ما يرام. لكن بعد شهر، تعود إلى المشروع لإضافة ميزة جديدة — وفجأة ينهار كل شيء. هل يبدو هذا مألوفًا؟ إذا كان الأمر كذلك، فإن TDD في PHP هو ما تحتاجه تمامًا. التطوير الموجه بالاختبارات (Test-Driven Development) ليس مجرد موضة عابرة، بل فلسفة تغير نظرتك للكود. في هذا المقال، سنشرح كيف يحول TDD الفوضى إلى نظام، والأخطاء إلى آثار من الماضي. ستتعلم كيفية كتابة اختبارات PHP التي توفر وقتك فعليًا، مع أمثلة عملية. هيا بنا!
\n\nما هو TDD ولماذا تحتاجه في PHP؟
\n\nTDD في PHP هو منهجية تبدأ بكتابة الاختبار أولاً، ثم كتابة الكود الذي يجتاز هذا الاختبار. يبدو غريبًا؟ في الحقيقة، إنه عبقري. بدلاً من التخمين حول ما إذا كان كودك يعمل، تحصل على تغذية راجعة فورية. المبادئ الأساسية لـ TDD:
\n\n- \n
- أحمر — اكتب اختبارًا يفشل (لأن الكود لم يُكتب بعد). \n
- أخضر — اكتب الحد الأدنى من الكود ليجتاز الاختبار. \n
- إعادة هيكلة — حسّن الكود دون كسر الاختبارات. \n
تتكرر هذه الدورة مرارًا وتكرارًا. في PHP، يعتبر TDD مفيدًا بشكل خاص لأن اللغة تُستخدم غالبًا في تطبيقات الويب، حيث يمكن أن تكون الأخطاء مكلفة. تساعد اختبارات PHPUnit (الإطار الرئيسي للاختبار) في تجنب الانتكاسات وتجعل الكود شفافًا. بالإضافة إلى ذلك، ينظم TDD عملك: تبدأ بالتفكير في التصميم قبل كتابة الكود.
\n\nإعداد بيئة اختبار PHP
\n\nقبل الغوص في الأمثلة، دعنا نجهز البيئة. لـ التطوير بالاختبارات في PHP، نحتاج إلى PHPUnit. التثبيت بسيط:
\n\ncomposer require --dev phpunit/phpunit ^10\n\nأنشئ مجلد tests في جذر المشروع. بداخله، أنشئ ملف CalculatorTest.php. تأكد من تثبيت PHP 8.0+. الآن كل شيء جاهز لأول اختبار.
الاختبار الأول: بناء آلة حاسبة باستخدام TDD
\n\nلنقم بإنشاء آلة حاسبة بسيطة. أولاً — الاختبار. هذا مثال كلاسيكي لـ TDD في PHP للمبتدئين.
\n\nالخطوة 1: أحمر (كتابة اختبار فاشل)
\n\nأنشئ tests/CalculatorTest.php:
<?php\n\nuse PHPUnit\\Framework\\TestCase;\n\nclass CalculatorTest extends TestCase\n{\n public function testAddition()\n {\n $calculator = new Calculator();\n $result = $calculator->add(2, 3);\n $this->assertEquals(5, $result);\n }\n}\n\nشغّل الاختبار:
\n\n./vendor/bin/phpunit tests/CalculatorTest.php\n\nنتوقع خطأ: Class "Calculator" not found. كل شيء حسب الخطة — هذه هي المرحلة الحمراء.
الخطوة 2: أخضر (كتابة الحد الأدنى من الكود)
\n\nأنشئ src/Calculator.php:
<?php\n\nclass Calculator\n{\n public function add(int $a, int $b): int\n {\n return $a + $b;\n }\n}\n\nلا تنس تضمين التحميل التلقائي في الاختبار:
\n\nrequire_once __DIR__ . '/../src/Calculator.php';\n\nشغّل الاختبار مرة أخرى — أخضر! الآن مرحلة إعادة الهيكلة. في هذه المرحلة، الكود بسيط، لكن لاحقًا يمكنك تحسينه دون خوف من كسره.
\n\nالخطوة 3: إعادة الهيكلة بثقة
\n\nلنفترض أننا نريد إضافة التحقق من الأنواع. نغير الكود:
\n\npublic function add(int $a, int $b): int\n{\n if (!is_int($a) || !is_int($b)) {\n throw new InvalidArgumentException('Only integers allowed');\n }\n return $a + $b;\n}\n\nشغّل الاختبارات — ما زالت ناجحة. يمنحك TDD الشجاعة للتجربة.
\n\nTDD المتقدم: التعامل مع الاستثناءات والـ Mocks
\n\nعندما تتقن الأساسيات، انتقل إلى السيناريوهات المعقدة. على سبيل المثال، اختبار الاستثناءات. في اختبارات الوحدة PHP، هذا