HTTP test
PHPUnit نسخه پایدار آن به صورت require-dev روی لاراول نصب است. همچنین Helper Method هایی برای استفاده هر چه بهتر از این tool در لاراول تعبیه شده است.
کلاس TestCase واقع در مسیر tests/TestCase.php
موجود است که هر کلاسی که ساخته می شود از این کلاس extends می شود که این ویژگی ها نیز در این کلاس می باشد.شما نیز می توانید متد های خود را به آن اضافه کنید.
برای اجرای آن از ریشه دستور زیر را اجرا کنید.
vendor/bin/phpunit
مسیر vendor/bin
مسیر فایل های اجرایی Command Line Interface می باشد. فایل های اجرای برای سیستم عامل های مبتنی بر unix و ویندوز (*.bat
) فایل اجرایی دارند.
فایل های تست به دو دسته تقسیم بندی می شوند :
- Feature : تست کاربری نرم افزار در راستای اجرای درخواست کامل از طریق Route .
- Unit : تست واحد یا single method testing . این همان PHPUnit می باشد.
فایل phpunit.xml
در ریشه نرم افزار موجود است.همچنین مسیر های ./tests/Unit
و ./tests/Feature
هم نام با موارد بالا پیکره بندی شده است.
اگر خطا در فایل تست شما باشد در console نمایش داده می شود. ولی اگر خطا مربوط به نرم افزار باشد تنها test خطا می دهد. برای این که خطاهای نرم افزار هم نمایش داده بشه Handler@report
کد زیر را اضافه کنید :
public function report(Exception $exception) { if(app()->environment() == "testing"){ throw $exception; } echo $exception->getMessage(); }
در حقیقت بدون وارد کردن کد بالا test تنها خطاهای مربوط به Assertion و syntax های مربوطه را نمایش می دهد.
Feature Test
تست کاربری با استفاده از امکانات routing نظیر get در دایرکتوری feature قرار می دهیم. این کلاس نیز از قوانین TestCase پیروی می کند. برای ایجاد یک Feature test باید دستور زیر را اجرا کنید(is valid route).
php artisan make:test UserTest
شایسته است برای تست داده های پایگاه داده از پایگاه داده جداگانه در حافظه استفاده کنید (DatabaseMigrations) چرا که این پایگاه داده خام است و بعد از تست از بین می رود و در نتیجه می توانید داده هایی که مستقیم وارد کرده اید (factory) همان جا تست کنید.
به طور مثال یک تست برای بررسی نمایش یک کتاب درقالب آرشیو به شکل زیر می سازیم.
class BookTest extends TestCase { use DatabaseMigrations; protected $book; protected function setup() { parent::setUp(); $this->book = factory(Book::class)->create(); } /** * show books correctly * @test * @return void */ public function bookList() { //create book $book = $this->book; //get request to book $response = $this->get('/book'); //check response status $response->assertStatus(200); //check response content $response->assertSee($book->name); } }
در کد بالا در متد BookList
یک داده خام داریم از یک جدول پایگاه داده خام و یک کتاب اضافه می کنیم و آن را به پایگاه داده خام اضافه می کنیم پس از آن :
- در ابتدا چک می کنیم که endpoint Route به درستی کار می کند.
- چک می کنیم که در صفحه به کاربر نمایش داده می شود یا خیر.
این یک درخواست تست به ازای نمایش archive کتاب ها می باشد.در لاراول برای این که یه سری مفاهیم درونی شناخته بشه از setUp استفاده شده. پس اگر نیاز داشتید به شکل بالا setUp را پیاده سازی کنید تا با خطا مواجه نشید.
یک سری Assertion مربوط به کلاس TestCase می باشد و برخی Assertion مربوط به Response می باشد که مربوط به لاراول است.
این بار با استفاده از متد post درخواست ارسال می کنیم. به طور خلاصه می توانیم Feature test را به درخواست و پاسخ مجازی تشبیه کنیم.
/** * insert new book * @test * @return void */ public function saveBook() { $data = ['name' => 'untitled book','type' => 'computer']; $response = $this->post('/book',$data); $this->assertDatabaseHas('books',$data); }
Unit Test
برای ایجاد یک test از جنس PHPUnit کد زیر را اجرا کنید (شایسته است در انتهای نام فایل Test را قرار دهید):
php artisan make:test UserTest --unit
تست ساخته شده یک کلاس extends شده از TestCase در مسیر tests/unit می باشد.
namespace Tests\Unit; use Tests\TestCase; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Foundation\Testing\RefreshDatabase; use App\User; class UserModelTest extends TestCase { use RefreshDatabase; /** * @test */ public function UserCreate() { $user = factory(User::class)->create(); return $this->assertRegExp('/^.+\@\S+\.\S+$/', $user->email); } }
کد بالا یک کاربر را می سازد و پس از آن ایمیل آن را چک می کند که معتبر باشد.از RefreshDatabase استفاده می کنیم تا کاربر ایجاد شده در پایگاه داده پس از تست حذف گردد.
Authentication Testing
با استفاده از متد actingAs از کلاس TestCase می توان یک کاربر را کاربر جاری کرد. به عنوان پارامتر ورودی باید یک کاربر به آن داد.
public function BuyBookError() { $book = factory(Book::class)->create(); $user = factory(User::class)->create(); //user known as logged in $this->actingAs($user); //buy book $user->buy($book); }
با استفاده از کد بالا اگر Action از auth middleware استفاده کند مشکلی بوجود نمی آید.
DataBase Testing
برای جلوگیری از تغییر پایگاه داده پس از تست آن می توان از trait های زیر استفاده کرد که همگی در مسیر Illuminate\Foundation\Testing
می باشند.
RefreshDatabases : تغییرات روی پایگاه داده اصلی اتفاق می افتد و بعد از انجام تست تغییرات همگی rollback می شوند.
DatabaseTransactions : رفتاری مشابه RefreshDatabases دارد.
DatabaseMigrations :پایگاه داده را پس از انجام تست از بین می برد. برای جلوگیری از مشکل ما از یک پایگاه داده دیگر در memory استفاده می کنیم.
در این روش ما یک پایگاه داده خام مجزا در حافظه استفاده می کنیم . به شکلی که پایگاه داده دوم را با درایوری غیر از درایور اصلی (مثلا اگر mysql است sqlite) در حافظه می سازیم و با استفاده از migration ها به ساختار آن ها دسترسی خواهیم داشت.
برای این کار باید در تنظیمات phpunit.xml
دو مورد DB_CONNECTION و DB_DATABASE را بیفزاییم:
<php> <env name="APP_ENV" value="testing"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_DRIVER" value="array"/> <env name="MAIL_DRIVER" value="array"/> <env name="QUEUE_CONNECTION" value="sync"/> <env name="SESSION_DRIVER" value="array"/> <!--Second Database env variable--> <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value=":memory:"/> <!--Second Database env variable--> </php>
دو مورد پایانی مربوط به تنظیمات DatabaseMigrations traitمی باشد. در طول اجرای برنامه نیاز است که درایور pdo_sqlite.dll در پی اچ پی شما نصب و فعال باشد.
پس از تنظیمات بالا هر جا در هر کلاسی از تست ما از DatabaseMigrations use کنیم روال گفته شده برای ما پیاده سازی می شود.
دیدگاهتان را بنویسید