برای اطمینان حاصل کردن از عملکرد وب سرویسی که نوشتهایم، در این آموزش قصد داریم تا نحوهٔ تستِ این ایپیآی با استفاده از یونیت تست را مورد بررسی قرار دهیم اما پیش از ادامه، توصیه میکنیم تا دورهٔ آموزش Unit Test در سکان آکادمی را بگذارنید که در آن نحوهٔ انجام یونیت تست با استفاده از لایبرری اپنسورس PHPUnit را آموزش دادهایم.
راهنمای نصب لایبرری PHPUnit
برای این منظور، وارد پوشهٔ rest-api-blog شده و کامند زیر را اجرا میکنیم:
/var/www/rest-api-blog$ composer require --dev phpunit/phpunitدر صورت موفقیتآمیز بودن عملیات فوق، فایل composer.json به صورت زیر آپدیت خواهد شد:
{
"autoload": {
"psr-4": {
"Core\\": "app/Core",
"Api\\": "app/Api"
}
},
"require": {
"firebase/php-jwt": "^5.0"
},
"require-dev": {
"phpunit/phpunit": "^8.1"
}
}میبینیم که داخل کلید require-dev نام این لایبرری درج گردیده است بدان معنا که این لایبرری فقط در محیط توسعهٔ نصب خواهد شد. حال نیاز به یک فایل پیکربندی برای فریمورک PHPUnit خواهیم داشت که در همین راستا در مسیر روت پروژه، فایلی تحت عنوان phpunit.xml حاوی محتویات زیر میسازیم:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./vendor/autoload.php"
colors="true"
verbose="true"
stopOnFailure="false">
<testsuites>
<testsuite name="Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
</phpunit>در این مرحله تمامی پیشنیازهای شروع به نوشتن تستها آماده بوده به طوری که با اجرای کامند زیر میتوان از این قضیه اطمینان حاصل کرد:
/var/www/rest-api-blog$ ./vendor/bin/phpunit
PHPUnit 8.1.5 by Sebastian Bergmann and contributors.
Runtime: PHP 7.3.5-1+ubuntu18.04.1+deb.sury.org+1
Configuration: /var/www/rest-api-blog/phpunit.xml
Time: 57 ms, Memory: 2.00 MB
No tests executed!با توجه به اینکه هیچ گونه تستی تاکنون ننوشتهایم، عبارت «!No tests executed» پس از اجرای کامند فوق در معرض دیدمان قرار میگیرد.
نحوهٔ نوشتن یونیت تست جهت آزمودن UserController
برای شروع، در مسیر روت پروژه فولدری تحت عنوان tests ساخته و داخل آن فایلی تحت عنوان UserControllerTest.php میسازیم که این وظیفه را خواهد داشت تا دو یونیت تست برای قابلیتهای ثبتنام کاربر جدید و لاگین را در خود جای دهد به طوری که داریم:
<?php
use Api\Config\Database;
use Api\Models\User;
use PHPUnit\Framework\TestCase;
class UserControllerTest extends TestCase
{
public function testCreateNewUser()
{
$user = new User((new Database())->connect());
$tmpUserData = [
'firstName' => 'Behzad',
'lastName' => 'Moradi',
'mail' => 'tmp.mail@example.com',
'pass' => '123456',
'salt' => '34879483792',
];
$isAdded = $user->create($tmpUserData);
if ($isAdded) {
$this->assertTrue($isAdded);
} else {
$this->assertFalse($isAdded);
}
}
public function testAuth()
{
$user = new User((new Database())->connect());
$result = $user->login('tmp.mail@example.com', '123456');
$isLoggedIn = $result->fetchAll(\PDO::FETCH_ASSOC);
$this->assertIsArray($isLoggedIn);
}
}ابتدا یک بار تست را اجرا کرده و خروجی آن را مشاهده میکنیم سپس به بررسی کدهای خواهیم پرداخت:
/var/www/rest-api-blog$ ./vendor/bin/phpunit
PHPUnit 8.1.5 by Sebastian Bergmann and contributors.
Runtime: PHP 7.3.5-1+ubuntu18.04.1+deb.sury.org+1
Configuration: /var/www/rest-api-blog/phpunit.xml
.. 2 / 2 (100%)
Time: 27 ms, Memory: 4.00 MB
OK (2 tests, 2 assertions)میبینیم که خروجی اجرای تست حاکی از آن است که هر دو با موفقیت پاس شدهاند اما در تفسیر کدهای فوق باید گفت که ابتدا متدی تحت عنوان ()testCreateNewUser ساختهایم که این وظیفه را دارا است تا قابلیت ثبت یک کاربر جدید را تست نماید. برای این منظور، داخل این متد آبجکتی تحت عنوان user$ از روی کلاس User ساخته و آبجکتی از کلاس Database را به عنوان ورودی به این کلاس پاس دادهایم. سپس آرایهای به نام tmpUserData$ ساختهایم که حاوی یکسری دیتای فرضی است و در ادامه این آرایه را به عنوان پارامتر ورودی متد ()create در نظر گرفتهایم. در واقع، چنانچه متد ()create با موفقیت اجرا شود، خروجی true را باز خواهد گرداند و از همین روی با استفاده از دستورات شرطی این موضوع را چک کردهایم به طوری که اگر مقدار متغیر isAdded$ برابر با true باشد، متد ()assertTrue را فراخوانی کرده و در غیر این صورت متد ()assertFalse فراخوانی خواهد شد.
متد ()testAuth نیز این وظیفه را دارا است تا قابلیت لاگین را تست کند و همچون متد قبلی، آبجکتی از روی مُدل User ساخته و متد ()login را روی آن فراخوانی کردهایم؛ سپس ایمیل و پسوردی صحیح را به عنوان پارامترهای ورودی این متد در نظر گرفتهایم به طوری که اگر چنین کاربری در دیتابیس وجود داشته باشد، یک آرایه برگردانده خواهد شد و از همین روی مقدار نهایی کوئری به دیتابیس را در متغیری به نام isLoggedIn$ ذخیره کرده و در نهایت آن را به متد ()assertIsArray پاس دادهایم بدین گونه که اگر پارامتر ورودی این متد آرایه باشد، تست پاس خواهد شد.
