جداکردن داده های هر تست در Laravel

جداکردن داده های هر تست در Laravel

فرایند تست کردن نرم‌افزار به منظور اطمینان از عدم وجود باگ در برنامه انجام می‌شود و ما عملکرد برنامه را در لایه‌های مختلف بررسی می‌کنیم.

این فرایند می‌تواند به صورت دستی انجام شود یا با نوشتن برنامه‌ای برای تست کردن برنامه‌ی ما، این فرایند خودکار شود. تست دستی مشکلات عدیده‌ای مثل امکان تست نشدن تمام کد و زمان‌بر بودن دارد. با اتوماتیک کردن پروسه تست برنامه، به راحتی می‌توان کد را ریفکتور (refactor) کرد و بهبود داد و از عملکرد درست برنامه مطمئن شد.

برای تست کردن برنامه، در زبان‌های مختلف فریمورک (framework) های بسیاری وجود دارد. در زبان php یکی از معروف‌ترین فریمورک‌ها، PHPUnit است که برای یادگیری و شروع تست‌نویسی در این فریمورک می‌توانید از دوره‌آموزشی آموزش Unit Test در اینجا استفاده کنید.

اما نکته بسیار مهمی که باید در تست‌نویسی به آن توجه کنیم این است که اطلاعات مربوط به هر تست با تست‌های دیگر تداخل پیدا نکند. در واقع هدف اصلی این است که هر تست برای خود یک دیتابیس ایزوله داشته باشد. برای مثال فرض کنید شما در تست شماره ۱، کاربری را اضافه می‌کنید. در تست شماره ۲ نیز برای تست قابلیت دیگری باید یک کاربر اضافه‌ کنید و توقع دارید همین یک کاربر در دیتابیس وجود داشته باشد در حالی که الآن دو کاربر وجود دارد. در این حالت برنامه در تست شماره ۲ قبول نمی‌شود حتی اگر به درستی کار کند. پس ما نیاز داریم اطلاعات هر تست را جدا کنیم و در پایان تست، آن‌ها را از بین ببریم.

Laravel یکی از معروف ترین فریمورک‌های php است که مدام در حال کامل‌تر شدن است. برای مثال شما می‌توانید در مقاله‌ی ویژگی های جدید Laravel 8 آخرین تغییرات آن را ببینید. این فریمورک از PHPUnit استفاده می‌کند و ابزاری در اختیار ما قرار می‌دهد که به آسانی برنامه‌های نوشته شده در لاراول را تست کنیم. لاراول ابزار‌های مختلفی را برای ایزوله کردن دیتابیس هر تست ارائه کرده است که در ادامه آن‌ها را شرح می‌دهیم.

متناسب با نوع دیتابیسی که برای تست استفاده می‌کنید روش‌های مختلفی برای ایزوله کردن استفاده می شود. در صورتی که از دیتابیس‌هایی که در حافظه مموری نگه‌داری می‌شوند استفاده می‌کنید، می‌توانید بدون نگرانی در مورد سرعت تست‌ها دیتابیس را پاک کنید و در تست بعدی آن را از نو بسازید. اما برای دیتابیس‌های دیگر این فرایند می تواند سنگین و پر هزینه باشد. فرض کنید شما یک دیتابیس sql دارید و درون لاراول migration های مربوط به پروژه خود را نوشته‌اید. حال می‌توانید دیتابیس را مثل قبل پاک کنید و از اول بسازید یا اینکه در آخر هر تست تغییراتی که در دیتابیس صورت گرفته‌اند را به حالت اول باز‌گردانید.

لاراول برای سناریو‌های مختلف راحت‌ترین راهکار را ارائه می‌دهد. اگر نیاز دارید که دیتابیس شما در ابتدای هر تست کاملا از نو ایجاد شود کافی است در کلاس تست خود از trait‌ای با نام DatabaseMigrations استفاده کنید. با این کار هر بار که تست‌های خود را اجرا می‌کنید در ابتدای هر تست شما یک دیتابیس تازه متولد شده در اختیار دارید و در آخر دیتابیس نابود می شود.

<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;
class ExampleTest extends TestCase
{
    use DatabaseMigrations;
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        // Run migrations
        $response = $this->get('/');
        $response->assertStatus(200);
        // Roll back migrations
    }
}

 سرعت اجرای تست‌ها در سناریو قبلی به دلیل اینکه در ابتدای هر تست دیتابیس از نو ساخته می‌شود پایین است. برای همین ممکن است این روش را انتخاب کنید که صرفا در انتهای هر تست تغییراتی که در دیتابیس داده‌اید را به حالت اول برگردانید. برای این منظور لاراول از مفهومی به عنوان transaction استفاده می‌کند. تنها با استفاده از ‌trait‌ای با نام DatabaseTransactions لاراول مسئولیت این کار را بر عهده می‌گیرد. این ابزار در انتهای هر تست تمامی تغییرات رخ داده درون دیتابیس را به حالت اول باز‌می‌گرداند.

البته توجه کنید که قبل از شروع تست‌ها شما باید دیتابیس را خودتان بسازید و migration ها را اجرا کنید.

<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
class ExampleTest extends TestCase
{
    use DatabaseTransactions;
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        // Start transaction
        $response = $this->get('/');
        $response->assertStatus(200);
        // Undo all of CHANGES in database
    }

در مستند لاراول به یک trait دیگر به نام RefreshDatabase اشاره شده که در ابتدا یکبار migration ها را اجرا می‌کند و برای ادامه تست‌ها مانند DatabaseTransactions عمل می‌کند. یعنی در انتهای هر تست تمامی تغییرات دیتابیس در آن تست را به حالت اولیه باز‌می‌گرداند. همچنین اگر شما از دیتابیسی درون مموری استفاده کنید لاراول در ابتدای هر تست یک دیتابیس جدید برای شما می سازد.

<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
    use RefreshDatabase;
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        // Database has been migrated at the beginning of test suit.
        // start transaction
        $response = $this->get('/');
        $response->assertStatus(200);
        // Undo all of CHANGES in database
    }
}

امیدوارم این مقاله به شما کمک کرده باشد. خوشحال می‌شوم نظرات خودتان در مورد این مقاله را با من به اشتراک بگذارید و اگر سوالی دارید بپرسید.

از بهترین نوشته‌های کاربران سکان آکادمی در سکان پلاس


online-support-icon