لماذا أصبح TDD معيارًا لمطوري PHP؟
تخيل: تكتب كودًا، تشغله، ترى خطأً، تصلحه - وهكذا في حلقة مفرغة. مألوف؟ والآن تخيل أنك تكتب أولاً اختبارًا سيفشل بالتأكيد، ثم تكتب الحد الأدنى من الكود لاجتيازه، وبعدها فقط تقوم بإعادة الهيكلة. هذا هو TDD في PHP - التطوير القائم على الاختبارات، الذي يحول الفوضى إلى نظام منظم.
يخشى العديد من المطورين TDD: "هذا سيبطئ التطوير!"، "لا أعرف كيف أختبر الكود القديم"، "PHPUnit معقد". لكن في الواقع، يوفر TDD ساعات من التصحيح ويجعل الكود مقاومًا للتغييرات. في هذه المقالة، سنشرح TDD بأمثلة PHP حقيقية، ونعرض كيف تعمل دورة "أحمر-أخضر-إعادة هيكلة"، ونقدم قوالب جاهزة للتطبيق.
ما هو TDD وكيف يعمل في PHP؟
التطوير القائم على الاختبارات (Test-Driven Development) هو منهجية حيث تُكتب الاختبارات قبل التنفيذ. الدورة الأساسية تبدو كالتالي:
- أحمر - نكتب اختبارًا لا ينجح (نتوقع خطأ).
- أخضر - نكتب الحد الأدنى من الكود لاجتياز الاختبار.
- إعادة هيكلة - نحسن الكود دون تغيير السلوك.
في PHP، يُستخدم غالبًا PHPUnit لـ TDD - إطار عمل قوي لاختبارات الوحدة. لكن TDD ليس عن الأدوات، بل عن الانضباط. دعنا نرى كيف يعمل ذلك عمليًا.
مثال 1: اختبار آلة حاسبة بسيطة
لنفترض أننا بحاجة لدالة جمع رقمين. بدون TDD، كنا سنكتب:
function add($a, $b) { return $a + $b;}echo add(2, 3); // 5مع TDD، نكتب أولاً الاختبار:
use PHPUnit\\Framework\\TestCase;
class CalculatorTest extends TestCase { public function testAdd() { $calculator = new Calculator(); $result = $calculator->add(2, 3); $this->assertEquals(5, $result); }}نشغله - يفشل الاختبار (أحمر). نكتب الحد الأدنى من التنفيذ:
class Calculator { public function add($a, $b) { return $a + $b; }}ينجح الاختبار (أخضر). لا حاجة لإعادة الهيكلة - الكود بسيط. لكن لو أردنا إضافة معالجة الأرقام السالبة، لكنا كتبنا اختبارًا لهذه الحالة أولاً.
مثال 2: TDD للعمل مع قاعدة البيانات
كثيرًا ما يُقال: "TDD غير مناسب لقواعد البيانات". هذه خرافة. استخدم الكائنات الوهمية (mocks) وقواعد بيانات الاختبار. لننظر إلى مثال مع UserRepository:
class UserRepositoryTest extends TestCase { public function testFindUserById() { $pdoMock = $this->createMock(PDO::class); $stmtMock = $this->createMock(PDOStatement::class); $pdoMock->method('prepare') ->willReturn($stmtMock); $stmtMock->method('fetch') ->willReturn(['id' => 1, 'name' => 'Alex']); $repository = new UserRepository($pdoMock); $user = $repository->findById(1); $this->assertEquals('Alex', $user['name']); }}يختبر الاختبار أن المستودع يستدعي SQL بشكل صحيح ويعالج النتيجة. سيكون كود التنفيذ في حده الأدنى: فقط تنفيذ الاستعلام وإرجاع البيانات.
الأدوات الشائعة لـ TDD في PHP
لكي يصبح TDD جزءًا من سير عملك، تحتاج إلى إتقان عدة أدوات:
- PHPUnit - الإطار الرئيسي للاختبارات. التثبيت:
composer require --dev phpunit/phpunit. - Mockery - مكتبة لإنشاء الكائنات الوهمية بواجهة برمجية مرنة.
- Prophecy - بديل لـ Mockery، يُستخدم غالبًا مع Symfony.
- PHPStan / Psalm - تحليل ثابت يكمل TDD باكتشاف الأخطاء قبل تشغيل الاختبارات.
للاختبارات التكاملية، يمكن استخدام Laravel Dusk أو Symfony Panther، لكن للبداية، يكفي