آموزش TDD در PHP
Test-Driven Development یا TDD یک روش توسعهٔ نرمافزار است که در آن ابتدا تستها نوشته میشوند و سپس کد پیادهسازی تا زمانی که تستها سبز شوند توسعه پیدا میکند. در PHP، TDD با ابزارهایی مثل PHPUnit بسیار کاربردی است و باعث تولید کد قابل تست، با کیفیت و قابل نگهداری میگردد.
چرا از TDD در پروژههای PHP استفاده کنیم؟
- کاهش باگها و افزایش اعتماد به تغییرات
- طراحی بهتر و تفکیک مسئولیتها (که منجر به کد تمیزتر میشود)
- مستندسازی رفتار سیستم از طریق تستها
- تسهیل رفرکتورینگهای آینده بدون ترس از شکستن عملکرد
آموزش گامبهگام: چرخهٔ Red-Green-Refactor
چرخهٔ سادهٔ TDD شامل سه مرحلهٔ اصلی است: نوشتن یک تست که شکست میخورد (Red)، نوشتن کدی که تست را عبور میدهد (Green)، سپس بهبود و تمیز کردن کد بدون تغییر رفتار (Refactor).
| مرحله | عمل |
|---|---|
| Red | نوشتن تست واحد جدید و مشاهده شکست |
| Green | نوشتن کدنویسی حداقلی تا تست پاس شود |
| Refactor | بهبود ساختار و حذف تکرارها با حفظ تستها |
راهاندازی محیط TDD در PHP
معمولاً از Composer برای مدیریت وابستگیها و از PHPUnit برای اجرای تستها استفاده میشود. یک فایل composer.json پایه:
{
"require-dev": {
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"App\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
}
}
}
این فایل مشخص میکند PHPUnit بهعنوان وابستگی توسعه نصب شود و فضای نام PSR-4 برای کد برنامه و تستها تنظیم گردد.
مثال عملی: نوشتن یک تست واحد ساده
فرض کنید میخواهیم یک کلاس Calculator داشته باشیم که جمع دو عدد را انجام دهد. ابتدا تست مینویسیم:
assertEquals(5, $calc->add(2, 3));
}
}
این تست میگوید متد add در کلاس Calculator باید مجموع 2 و 3 را برابر 5 برگرداند. در ابتدا این تست باید شکست بخورد چون کلاس Calculator هنوز وجود ندارد.
نوشتن حداقلی کد برای پاس کردن تست
<?php
namespace App;
class Calculator
{
public function add($a, $b)
{
return $a + $b;
}
}
این پیادهسازی ساده تست را سبز میکند. هدف در فاز Green نوشتن کمترین کدی است که تست را پاس کند، سپس در فاز Refactor میتوان بهینهسازی کرد.
الگو: Arrange-Act-Assert
تستها را با الگوی AAA بنویسید: آمادهسازی (Arrange)، اجرای اقدام (Act)، بررسی نتیجه (Assert). این ساختار خوانایی تستها را بالا میبرد و پیگیری خطا را سادهتر میکند.
تستهای واحد و وابستگیها — Mock و فیک
برای کلاسهایی که وابستگی خارجی مثل دیتابیس یا سرویس HTTP دارند، باید وابستگیها را تزریق کنیم و در تست از Mock یا Stub استفاده نماییم. مثال استفاده از mocking در PHPUnit:
createMock(UserRepository::class);
$repo->expects($this->once())
->method('save')
->willReturn(true);
$service = new UserService($repo);
$this->assertTrue($service->register('alice'));
}
}
در این مثال یک Mock از UserRepository ساختهایم و انتظار داریم متد save دقیقاً یک بار فراخوانی شود و مقدار true برگرداند. سپس UserService را با این mock تست میکنیم تا از اجرای درست منطق اطمینان حاصل گردد.
نکات حرفهای در پیادهسازی TDD در PHP
- کدتان را کوچک و تکوظیفهای نگه دارید تا تستپذیری بالا برود.
- از تزریق وابستگی (Dependency Injection) استفاده کنید تا تستها مستقل شوند.
- تستهای واحد باید سریع باشند — اگر تستها کند شوند، تیم از اجرای مداوم آنها صرفنظر خواهد کرد.
- برای تستهای پیچیده از تستهای یکپارچه (Integration Tests) در کنار واحد استفاده کنید و آنها را جدا نگه دارید.
- در پوششدهی (Coverage) افراط نکنید؛ هدف کیفیت، نه درصد پوشش مطلق.
چگونه تستها را در CI اجرا کنیم؟
در فایل CI (مثل GitHub Actions یا GitLab CI) کافی است دستورات Composer و PHPUnit را اجرا کنید:
composer install --no-interaction --prefer-dist
vendor/bin/phpunit --configuration phpunit.xml --colors=always
این دستورات وابستگیها را نصب و تستها را اجرا میکنند. پیشنهاد میشود گزارش خروجی و یا پوشش تست را در CI ثبت کنید.
نمونه ساختار پروژه
| مسیر | شرح |
|---|---|
| src/ | کد برنامه (کلاسها و منطق) |
| tests/ | تستهای واحد و یکپارچه |
| composer.json | مدیریت وابستگیها |
| phpunit.xml | پیکربندی PHPUnit |
جمعبندی و بهترین شیوهها
TDD در PHP یک ابزار قدرتمند برای توسعهٔ نرمافزار با کیفیت بالا است. با رعایت چرخهٔ Red-Green-Refactor، استفاده از PHPUnit، تزریق وابستگی و نوشتن تستهای خوانا و سریع میتوانید ریسکها را کاهش دهید و اعتماد به کد را افزایش دهید.
شروع با تستهای کوچک، نگهداری تستها در CI، و تمرکز بر طراحی قابل تست به شما کمک میکند تا به مرور به یک فرایند توسعهٔ تستمحور موفق در پروژههای PHP دست پیدا کنید.
آیا این مطلب برای شما مفید بود ؟



