برای اطمینان حاصل کردن از عملکرد وب سرویسی که نوشتهایم، در این آموزش قصد داریم تا نحوهٔ تستِ این ایپیآی با استفاده از یونیت تست را مورد بررسی قرار دهیم اما پیش از ادامه، توصیه میکنیم تا دورهٔ آموزش 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
پاس دادهایم بدین گونه که اگر پارامتر ورودی این متد آرایه باشد، تست پاس خواهد شد.