آموزش تست نویسی در لاراول

How to Get Started with Unit Testing in Laravel

16 شهریور 1402
آموزش تست نویسی در لاراول

تست مرحله مهمی در چرخه عمر توسعه نرم افزار است. این کار تضمین می کند کدی که نوشته اید قبل از اینکه قسمت بعدی پروژه خود را پیاده سازی همانطور که طراحی شده است کار می کند. هر بار که نوشتن یک جز نرم افزاری را به پایان می رسانید، باید یک تست نیز بنویسید تا بررسی کنید که رفتار آن با انتظارات شما مطابقت دارد. این فرآیند به حفظ کیفیت کد شما کمک می کند. بنابراین بیاید برای آموزش تست نویسی در لاراول وقت بگذرایم!

وقتی در مورد تست کردن در لاراول صحبت می کنیم، معمولا دو چیز را در نظر می گیریم: یونیت تست و فیچر تست. یونیت تست فقط بر روی یک قطعه کوچک از کد (معمولا متدی در داخل یک کلاس) تمرکز می‌کند، در حالی که فیچر تست بررسی می‌کند آیا یک ویژگی خاص، که ممکن است متشکل از چندین متد یا کلاس در ارتباط با یکدیگر باشد، به روشی که شما طراحی کرده‌اید کار می‌کند یا خیر.

در این آموزش قصد داریم در مورد نحوه نوشتن یونیت تست ها در پروژه لاراول یا آموزش تست نویسی در لاراول با استفاده از PHPUnit، محبوب ترین پکیج یونیت تست برای پروژه های PHP صحبت کنیم. این پکیج به خوبی با لاراول پیکربندی شده است، بنابراین پس از ایجاد یک پروژه جدید لاراول نیازی به پیکربندی اضافی نیست.

نکته ای که باید به آن توجه کنید این است که اگر چه PHPUnit در اصل برای یونیت تست طراحی شده است، اگر از آن برای فیچر تست نیز استفاده کنید هیچ مشکلی ندارد. این پکیج شامل بسیاری از assert های قدرتمند است که می تواند در بسیاری از حالت های مختلف تست کردن مفید باشد.

در ادامه این آموزش، ویژگی های یونیت تست در لاراول را خواهید آموخت:

  • ایجاد و اجرای تست ها
  • درک نحوه استفاده از assert ها در PHPUnit
  • تست سرورهای HTTP
  • تست APIهای JSON و HTML
  • نحوه تولید داده های فیک برای تست
  • درک تست مرورگر با Laravel Dusk
  • mocking (ماکینگ) در لاراول
  • پیکربندی و ساخت یک ورک فلو برای تست یکپارچه سازی مداوم

پیش نیازها برای یادگیری تست نویسی در لاراول

قبل از ادامه این آموزش، مطمئن شوید که شرایط زیر را دارید:

  • درک اولیه ای از PHP
  • یک ویرایشگر کد (مانند Visual Studio Code) روی رایانه خود نصب کرده باشید
  • PHP (نسخه ۸.۰ یا جدیدتر) را روی دستگاه خود نصب باشید
  • اگر از رایانه شخصی و ویندوز استفاده می کنید، مطمئن شوید که WSL2 و Docker Desktop را روی دستگاه خود نصب باشید
  • اگر از مک استفاده می کنید، فقط باید Docker Desktop را نصب کنید
  • اگر از لینوکس استفاده می کنید، لطفا Docker Compose را نصب کنید
  • Google Chrome را برای آزمایش مرورگر از طریق Laravel Dusk نصب کرده باشید.
  • اگر یک حساب GitHub ندارید، ثبت نام کنید. ما از آن برای تنظیم ورک فلو CI/CD برای آزمایش در مرحله آخر این مقاله استفاده خواهیم کرد

مرحله 1 - ایجاد یک پروژه جدید لاراول

بیایید با ایجاد یک پروژه جدید لاراول از ابتدا شروع کنیم. تیم لاراول ابزاری به نام Laravel Sail ارائه کرده است که به ما اجازه می دهد تا زمانی که Docker را نصب و اجرا می کنیم، بدون توجه به سیستم عاملی که استفاده می کنیم، به سرعت یک پروژه را راه اندازی کنیم.

ترمینال را باز کنید و دستور زیر را برای ایجاد یک پروژه جدید اجرا کنید:

curl -s https://laravel.build/<your_project_name> | bash

با این کار یک پروژه لاراول جدید در دایرکتوری که دستور را در آن اجرا کرده اید ایجاد می شود. بعد، وارد پروژه ای که به تازگی ایجاد کرده اید شوید:

cd <your_project_name>

در دایرکتوری پروژه، دستور sail up را مطابق شکل زیر اجرا کنید. مطمئن شوید که هر نمونه ای از Redis یا MySQL را در صورتی که روی دستگاه شما اجرا می شود متوقف کنید، در غیر این صورت ممکن است با خطاهایی در مورد در دسترس نبودن پورت ها مواجه شوید.

./vendor/bin/sail up

Laravel Sail به طور خودکار هر آنچه را که نیاز دارید در داخل یک کانتینر داکر نصب می کند، مانند پایگاه داده، Redis، و حتی یک سرور ایمیل، و تنها کاری که باید انجام دهیم این است که منتظر بمانیم. (build کردن) ساخت برای اولین بار ممکن است چند دقیقه طول بکشد، اما build ‌های بعدی بسیار سریع‌تر خواهند بود. اگر خروجی زیر را مشاهده کردید به این معنی است که Laravel Sail با موفقیت راه اندازی شده است.

خروجی:

Starting code_mailhog_1 ...
Starting code_mailhog_1     ... done
Starting code_redis_1       ... done
Starting code_meilisearch_1 ... done
Starting code_mysql_1       ... done
Creating code_laravel.test_1 ... done
. . .
laravel.test_1  | Starting Laravel development server: http://0.0.0.0:80
laravel.test_1  | [Thu Jun  2 17:37:32 2022] PHP 8.1.5 Development Server (http://0.0.0.0:80) started

مرحله 2 - بررسی تنظیمات پیش فرض تست در لاراول

قبل از شروع تست نویسی، بیایید نگاهی به تست های پیش فرضی که لاراول برای ما ارائه کرده است بیاندازیم. این کار به ما کمک می کند تا بفهمیم تست در لاراول چگونه کار می کند.

فایل phpunit.xml

یک فایل phpunit.xml در دایرکتوری root پروژه وجود دارد. این فایل پیکربندی برای PHPUnit، و یک فریم ورک آزمایشی برای برنامه های PHP است. مطابق شکل زیر به سه بخش اصلی تقسیم می شود:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <coverage processUncoveredFiles="true">
        <include>
            <directory suffix=".php">./app</directory>
        </include>
    </coverage>
    <php>
        <env name="APP_ENV" value="testing" />
        <env name="BCRYPT_ROUNDS" value="4" />
        <env name="CACHE_DRIVER" value="array" />
        <env name="DB_DATABASE" value="testing" />
        <env name="MAIL_MAILER" value="array" />
        <env name="QUEUE_CONNECTION" value="sync" />
        <env name="SESSION_DRIVER" value="array" />
        <env name="TELESCOPE_ENABLED" value="false" />
    </php>
</phpunit>

در قسمت <testsuites> دو نوع تست مختلف برای ما از پیش تعریف شده است. این بخش به PHPUnit می‌گوید که تست ‌هایی را که در دایرکتوری‌های tests/Unit/. و tests/Feature/. ذخیره می‌شوند، اجرا کند. در مرحله بعدی این آموزش نگاه دقیق تری به هر دو دایرکتوری خواهیم داشت.

در مرحله بعد، بخش <coverage> جایی است که ما تعریف می کنیم چه کد و چه دایرکتوری هایی در تست پوشش داده شده اند و چگونه پوشش داده می شوند. برای این آموزش مهم نیست، بنابراین می توانیم آن را همانطور که هست رها کنیم.

در نهایت در قسمت <php> می توانیم متغیرهای محیطی را برای محیط تست تعریف کنیم. هنگام اجرای یک آزمایش، متغیرهای تعریف شده در اینجا، متغیرهای تعریف شده در فایل .env را که در ریشه پروژه نیز وجود دارد، بازنویسی می کنند.

دایرکتوری tests

دایرکتوری tests جایی است که ما تمام فایل های آزمایشی خود را ذخیره می کنیم. تست های ویژگی باید در دایرکتوری tests/Feature باشد، در حالی که یونیت تست ها باید در پوشه tests/Unit باشد. PHPUnit به طور خودکار تست هایی را که در داخل این دایرکتوری ها ذخیره شده اند، همانطور که در فایل phpunit.xml تعریف شده است، جستجو و اجرا می کند. فایل های CreatesApplication.php و TestCase.php برنامه را قبل از اجرای تست ها بوت می کنند. ما نیازی به تغییر چیزی در این فایل ها نداریم.

بیایید به یک نمونه تست نگاهی بیندازیم. فایل tests/Unit/ExampleTest.php/. را در ویرایشگر متن خود باز کنید:

code ./tests/Unit/ExampleTest.php

tests/Unit/ExampleTest.php/.

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function test_that_true_is_true()
    {
        $this->assertTrue(true);
    }
}

این تست نمونه کاملا ابتدایی و ساده است زیرا درست بودن تست را بررسی می کند. متد ()assertTrue منتظر دستوری است که مقدار بولی true را برمی گرداند. این متد یک assert نامیده می شود و PHPUnit بسیاری از assert های مفید دیگر را در اختیار ما قرار می دهد که در ادامه این مقاله به آنها پرداخته خواهد شد. شما می توانید لیست کاملی از تمام assert های PHPUnit را در اسناد رسمی آنها بیابید.

برای اجرای این تست، یک ترمینال جدید را باز کنید (به طوری که Laravel Sail همچنان در حال اجرا باشد) و دستور زیر را اجرا کنید. مطمئن شوید که در دایرکتوری اصلی پروژه خود هستید.

./vendor/bin/phpunit

خروجی:

Time: 00:00.123, Memory: 20.00 MB OK (2 tests, 2 assertions)

این خروجی نشان می دهد که لاراول دو تست و دو assert را اجرا کرده است (تست نمونه دیگری در دایرکتوری Feature وجود دارد که شامل assert دیگری است) و هر دو موفقیت آمیز هستند.

ما می‌توانیم با تغییر آرگومان ارسال شده به متد ()assertTrue مطابق شکل زیر باعث شکست تست شویم:

tests/Unit/ExampleTest.php/.

. . .
public function test_that_true_is_true()
{
    $this->assertTrue("this is a string");

}
. . .

حالا دوباره تست را اجرا کنید:

./vendor/bin/phpunit

خروجی:

Time: 00:00.141, Memory: 20.00 MB

There was 1 failure:

1) Tests\Unit\ExampleTest::test_that_true_is_true
Failed asserting that 'this is a string' is true.

/Users/erichu/Documents/GitHub/laravel-unit-test/code/tests/Unit/ExampleTest.php:16

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.

وقتی تغییرات بالا را لغو کردید، تست باید دوباره پذیرفته شود. در مرحله بعد، بیایید با ایجاد تست دیگری در زیر تابع  ()test_that_true_is_true مورد هیجان انگیزتری را امتحان کنیم:

tests/Unit/ExampleTest.php/.

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    . . .

    /**
     * A basic test example.
     *
     * @return void
     */
    public function test_that_name_is_jack()
    {
        $name = "John";
        // $name = "Jack";
        $this->assertTrue($name == "Jack");
    }
}

از آنجایی که متغیر  name$ با John مقداردهی شده است، بدیهی است که John برابر با Jack نیست، و این تست با شکست مواجه خواهد شد.

این تست را با دستور زیر اجرا کنید:

./vendor/bin/phpunit

خروجی:

Time: 00:00.008, Memory: 8.00 MB

There was 1 failure:

1) Tests\Unit\ExampleTest::test_that_name_is_jack
Failed asserting that false is true.

/Users/erichu/Documents/GitHub/laravel-unit-test/code/tests/Unit/ExampleTest.php:29

FAILURES!

Tests: 2, Assertions: 2, Failures: 1.

قبل از اینکه به مرحله بعدی ادامه دهید، name$ را به "Jack" تغییر دهید تا در تست های بعدی با شکست مواجه نشوید.

مرحله 3 - ایجاد یک تست از ابتدا

در این بخش، نحوه ایجاد تست های خود را از ابتدا یاد خواهیم گرفت. کد زیر کدی است که ما تست خواهیم کرد. اتاقی را تعریف می کند که شامل چند نفر است. می‌توانیم فرد جدیدی را به اتاق اضافه کنیم، فردی را از اتاق خارج کنیم و بررسی کنیم که آیا فردی در اتاق است یا خیر.

یک فایل app/Room.php جدید در ویرایشگر خود ایجاد کنید و کد زیر را در فایل قرار دهید:

code app/Room.php

app/Room.php/.

<?php

namespace App;

class Room
{
  /**
   * @var array
   */
  protected $people = [];

  /**
   * Constructor. Fill the room with the given people.
   *
   * @param array $people
   */
  public function __construct($people = [])
  {
    $this->people = $people;
  }

  /**
   * Check if the specified person is in the room.
   *
   * @param string $person
   * @return bool
   */
  public function has($person)
  {
    return in_array($person, $this->people);
  }

  /**
   * Add a new person to the room.
   *
   * @param string $person
   * @return array
   */
  public function add($person)
  {
    array_push($this->people, $person);
    return $this->people;
  }

  /**
   * Remove a person from the room.
   *
   * @param string $person
   * @return array
   */
  public function remove($person)
  {
    if (($key = array_search($person, $this->people)) !== false) {
      unset($this->people[$key]);
    }
    return $this->people;
  }
}

اکنون، بیایید یک یونیت تست جدید با دستور زیر ایجاد کنیم:

./vendor/bin/sail php artisan make:test RoomTest --unit

خروجی:

Test created successfully.

دستور بالا یک فایل RoomTest.php در دایرکتوری tests/Unit ایجاد می کند و آن را با مقداری کد از پیش نوشته شده پر می کند:

tests/Unit/RoomTest.php/.

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class RoomTest extends TestCase
{
    /**
     * A basic unit test example.
     *
     * @return void
     */
    public function test_example()
    {
        $this->assertTrue(true);
    }
}

assert های ()assertTrue و ()assertFalse

ادامه دهید و فایل tests/Unit/RoomTest.php ایجاد شده را باز کنید و محتویات آن را به صورت زیر تغییر دهید:

tests/Unit/RoomTest.php/.

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

// Import the room
use App\Room;


class RoomTest extends TestCase
{
    /**
     * Test the has() method in Room class
     *
     * @return void
     */
    public function test_room_has()
    {
        $room = new Room(["Jack", "Peter", "Amy"]); // Create a new room

        $this->assertTrue($room->has("Jack")); // Expect true

        $this->assertFalse($room->has("Eric")); // Expect false

    }
}

ما قبلا متد ()assertTrue را در مرحله 2 دیده‌ایم. متد ()assertFalse به همین روش کار می‌کند با این تفاوت که به یک مقدار false نیاز دارد. در این مثال، "Jack" در اتاق است و "Eric" نیست، بنابراین room->has("Jack")$ مقدار true و room->has("Eric")$  مقدار false را برمی‌گرداند، که باعث می‌شود هر دو assertion پذیرفته شوند (pass شوند).

با اجرای دستور زیر می توانید آن را تست کنید. توجه داشته باشید که می‌توانیم با تعیین مسیر فایل مانند این، یک فایل تست خاص را اجرا کنیم:

./vendor/bin/phpunit tests/Unit/RoomTest.php

خروجی:

Time: 00:00.012, Memory: 10.00 MB OK (1 tests, 2 assertions)

()assertContains

بیایید تست دیگری برای بررسی رفتار متد add بنویسیم. به جای ()assertTrue یا ()assertFalse، راه دیگری را امتحان خواهیم کرد. یک شخص جدید به اتاق اضافه می کنیم، سپس با استفاده از متد ()assertContains بررسی می کنیم که آیا اتاق این شخص خاص را دارد یا خیر.

تابع زیر را به کلاس RoomTest در متد ()test_room_has اضافه کنید:

tests/Unit/RoomTest.php/.

. . .
/**
 * Test the add() method in Room class
 *
 * @return void
 */
public function test_room_add()
{
    $room = new Room(["Jack"]); // Create a new room
    $this->assertContains("Peter", $room->add("Peter"));

}


()assertContains دو پارامتر دارد: اولی مقداری است که انتظار داریم آرایه باشد، و دومین پارامتر مقداری است که قرار است داشته باشد.

در مثال ما، یک اتاق جدید که فقط شامل Jack است ایجاد می شود و سپس room->add("Peter")$ را به اتاق اضافه می کند. در نهایت، از ()assertContains استفاده می کنیم تا بررسی کنیم که آیا Peter در اتاق است یا خیر.

تست را با دستور زیر اجرا کنید:

./vendor/bin/phpunit tests/Unit/RoomTest.php

باید توجه داشته باشید که تست با موفقیت انجام می شود:

خروجی:

Time: 00:00.007, Memory: 8.00 MB OK (2 tests, 3 assertions)

لاراول همچنین یک ابزار خط فرمان قدرتمند به نام artisan ارائه می دهد که می توانیم از آن برای اجرای تست های خود نیز استفاده کنیم. دستور artisan خروجی دقیق تری ارائه می دهد:

./vendor/bin/sail php artisan test

خروجی:

PASS  Tests\Unit\ExampleTest
✓ that true is true
✓ that name is jack

 PASS  Tests\Unit\RoomTest
✓ room has
✓ room add

Tests:  4 passed
Time:   1.47s

با کمک دستور artisan این امکان برای ما وجود دارد که بررسی کنیم چه مقدار از کد ما تحت پوشش تست ها است. ابتدا باید یک پسوند PHP به نام Xdebug را با پیروی از این دستورالعمل ها نصب کنیم.

هنگامی که Xdebug نصب شد، باید یک متغیر محیطی جدید در فایل .env اضافه کنیم تا حالت coverage آن را فعال کنیم: 

env.

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:S07501pjvBOoBrOPMFMUg5J4Gyurq9FKDLWuIkwt5tk=
APP_DEBUG=true
APP_URL=http://app.test

. . .

SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://meilisearch:7700

SAIL_XDEBUG_MODE=develop,debug,coverage

پس از ذخیره فایل env.، باید Laravel Sail را با فشار دادن Ctrl-C در ترمینال متوقف کرده و دوباره راه اندازی کنید و  vendor/bin/sail up/. را یک بار دیگر اجرا کنید. اکنون، می‌توانیم دستور artisan test را با پرچم --coverage  اجرا کنیم تا ببینیم چه مقدار از کد ما تحت پوشش تست‌ها است:

./vendor/bin/sail php artisan test --coverage

خروجی:

PASS  Tests\Unit\ExampleTest
✓ that true is true
✓ that name is jack

 PASS  Tests\Unit\RoomTest
✓ room has
✓ room add

Tests:  4 passed
Time:   1.17s

Console/Kernel  ........................................... 100.0 %
Exceptions/Handler  ....................................... 100.0 %
Http/Controllers/Controller  .............................. 100.0 %
Http/Kernel  .............................................. 100.0 %
Http/Middleware/Authenticate ................................ 0.0 %
Http/Middleware/EncryptCookies  ........................... 100.0 %
Http/Middleware/PreventRequestsDuringMaintenance  ......... 100.0 %
Http/Middleware/RedirectIfAuthenticated ..................... 0.0 %
Http/Middleware/TrimStrings  .............................. 100.0 %
Http/Middleware/TrustHosts .................................. 0.0 %
Http/Middleware/TrustProxies  ............................. 100.0 %
Http/Middleware/VerifyCsrfToken  .......................... 100.0 %
Models/User  .............................................. 100.0 %
Providers/AppServiceProvider  ............................. 100.0 %
Providers/AuthServiceProvider  ............................ 100.0 %
Providers/BroadcastServiceProvider .......................... 0.0 %
Providers/EventServiceProvider  ........................... 100.0 %
Providers/RouteServiceProvider 32..37, 49 .................. 33.3 %
Room  ..................................................... 100.0 %

Total Coverage ............................................. 48.4 %

همانطور که می بینید، درصد پوشش کد برای هر فایل در زیر نتایج آزمون ذکر شده است و ما 48.4٪ پوشش تست کلی برای برنامه خود داریم.

()assertCount

تست نهایی ما برای کلاس Room شامل تست متد ()remove با ()assertCount است. این متد مشابه ()assertContains عمل می کند، با این تفاوت که اولین پارامتر باید تعداد آیتم های آرایه باشد.

تابع زیر را در زیر متد ()test_room_add اضافه کنید:

tests/Unit/RoomTest.php/.

/**
 * Test the add() method in Room class
 *
 * @return void
 */
public function test_room_remove()
{
    $room = new Room(["Jack", "Peter"]); // Create a new room
    $this->assertCount(1, $room->remove("Peter"));
}




تابع بالا یک اتاق جدید با دو عضو ایجاد می کند و از متد ()assertCount برای آزمایش اینکه آیا حذف یک عضو از اتاق تعداد اعضای آن را به 1 کاهش می دهد یا خیر استفاده می کند.

برای مشاهده نتایج دوباره تست را تکرار کنید:

./vendor/bin/sail php artisan test ./tests/Unit/RoomTest.php

خروجی:

PASS  Tests\Unit\RoomTest
✓ room has
✓ room add
✓ room remove

Tests:  3 passed
Time:   1.47s

مرحله 4 - تست پاسخ های HTTP

در یک برنامه وب واقعی، احتمالا مانند مرحله قبل نیازی به آزمایش آرایه های ساده نخواهیم داشت. در عوض، احتمالا با API ها، درخواست های HTTP و پاسخ ها سر و کار خواهیم داشت. لاراول همچنین نمونه ای از این نوع تست را ارائه می دهد.

ادامه دهید و فایل ./tests/Feature/ExampleTest.php را در ویرایشگر متن خود باز کنید:

code ./tests/Feature/ExampleTest.php

tests/Feature/ExampleTest.php/.

public function test_the_application_returns_a_successful_response()
{
    $response = $this->get('/');

    $response->assertStatus(200);
}

در این مثال، یک درخواست GET به URL روت ارسال می شود و پاسخ برگشتی به متغیر response اختصاص داده می شود. در خط زیر، بررسی می کنیم که آیا پاسخ دارای کد موفقیت 200 با assertStatus است.

گاهی اوقات، یک endpoint از ما می خواهد که برخی از پارامترهای کوئری را ارسال کنیم. در چنین مواردی می توانیم این کار را انجام دهیم:

public function test_the_application_returns_a_successful_response()
{
    $response = $this->post('/user', ['name' => 'Amy']);


    $response->assertStatus(200);
}

فقط تست status پاسخ برای یک برنامه واقعی کافی نیست. معمولا باید body پاسخ را آزمایش کنیم تا مطمئن شویم داده هایی که به ما بازگردانده می شوند معتبر هستند و با انتظارات مطابقت دارند. در بیشتر موارد، داده های پاسخ یا در قالب JSON یا HTML هستند. در دو بخش بعدی، نحوه آزمایش هر دو را به تفصیل مورد بحث قرار خواهیم داد.

تست داده های JSON

بک‌اند و فرانت‌اند اکثر برنامه‌های کاربردی وب مدرن معمولا جداگانه اجرا می‌شوند و داده‌ها در قالب JSON بین آنها به اشتراک گذاشته می‌شود. لاراول برای آزمایش اینکه داده‌های JSON دریافت شده از endpoint معتبر و دقیق هستند، کمک‌هایی به ما ارائه می‌دهد. به عنوان مثال، متد ()assertJson برای اطمینان از اعتبار داده های JSON ارائه شده است.

بیایید نگاهی به مثال زیر بیاندازیم. فایل routes/web.php را باز کنید و یک مسیر جدید ایجاد کنید. وقتی درخواست GET برای آن ارسال شد، کاری میکنیم این مسیر داده‌های JSON را برگرداند.

code routes/web.php

routes/web.php/.

. . .
Route::get('/json-test', function () {
    return response()->json([
        'name' => 'Jone',
        'updated' => true,
    ]);
});

با استفاده از دستور زیر یک تست لاراول برای این مسیر ایجاد کنید:

./vendor/bin/sail php artisan make:test JSONTest

خروجی:

Test created successfully.

tests/Feature/JSONTest.php/. جدید ایجاد شده را باز کنید و محتویات آن را به صورت زیر تغییر دهید:

tests/Feature/JSONTest.php/.

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class JSONTest extends TestCase
{
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function test_json()
    {
        $response = $this->get('/json-test');

        $response->assertStatus(200);
        $response->assertJson([

            'updated' => true,

        ]);

    }
}


در این تست، یک درخواست GET به مسیر json-test/ می فرستیم و پاسخ آن را به در متغیر $response قرار می‌دهیم. در مرحله بعد، ما تست می کنیم که آیا status پاسخ 200 است، و آیا داده های پاسخ حاوی مقدار 'updated' => true است یا نه.

اگر اکنون این تست را اجرا کنید، هر دو assert باید قبول شوند:

./vendor/bin/sail php artisan test ./tests/Feature/JSONTest.php

خروجی:

 PASS  Tests\Feature\JSONTest
✓ json

Tests:  1 passed
Time:   0.69s

تست بالا فقط بررسی می‌کند که پاسخ JSON دارای property موردنظر باشد. در مواردی که می‌خواهید داده‌های JSON دقیقا مطابقت داشته باشند، می‌توانید از ()assertExactJson مانند این استفاده کنید:

. . .
public function test_json()
{
    $response = $this->get('/json-test');

    $response->assertStatus(200);
    $response->assertExactJson([

        'updated' => true,

    ]);

}
. . .

پس از انجام تغییرات فوق، تست با شکست مواجه خواهد شد زیرا JSON ارائه شده دقیقا با پاسخ مطابقت ندارد.

./vendor/bin/sail php artisan test ./tests/Feature/JSONTest.php

خروجی:

 FAIL  Tests\Feature\JSONTest
⨯ json

---

• Tests\Feature\JSONTest > json
Failed asserting that two strings are equal.

at tests/Feature/JSONTest.php:25
   21▕         // $response->assertJson([
   22▕         //     'created' => true,
   23▕         // ]);
   24▕         $response->assertExactJson([
➜  25▕             'created' => true,
   26▕         ]);
   27▕     }
   28▕ }
--- Expected
+++ Actual
@@ @@
 '{\n
-    "created": true\n
+    "created": true,\n
+    "name": "Abigail"\n
 }'

Tests:  1 failed
Time:   0.76s

تست ویوهای HTML

گاهی اوقات، ما انتظار داریم یک مسیر به جای JSON یک مقدار HTML را برگرداند. لاراول همچنین قادر است پاسخ های HTML را برای ما تست کند تا بتوانیم بررسی کنیم که مسیر به درستی کار می کند.

قبل از نوشتن یک تست جدید، بیایید ویو و روتر مورد آزمایش را ایجاد کنیم. به دایرکتوری ./resources/views بروید و یک فایل جدید به نام test.blade.php ایجاد کنید.

code ./resources/views/test.blade.php

resources/views/test.blade.php/.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <p>The name is {{ $name }}.</p>
</body>

</html>



این ویو یک متغیر name را نیاز دارد و این متغیر را می توان از روتر تهیه کرد. به فایل  ./routes/web.php بروید و مسیر زیر را ایجاد کنید:

routes/web.php/.

. . .
Route::get('/view-test', function () {
    return view('test', ['name' => 'Taylor']);
});

در مرحله بعد، بیایید یک کلاس تست جدید برای ویویی که ایجاد کردیم بسازیم و آن را ViewTest.php بنامیم:

./vendor/bin/sail php artisan make:test ViewTest

خروجی:

Test created successfully.

فایل tests/Feature/ViewTest.php/. را باز کرده و تست زیر را ایجاد کنید:

code ./tests/Feature/ViewTest.php

tests/Feature/ViewTest.php/.

. . .
class ViewTest extends TestCase
{
    /**
     * Test if the returned HTML page contains the name Taylor.
     *
     * @return void
     */
    public function test_if_view_contains_Taylor()
    {
        $response = $this->get('/view-test');

        $response->assertStatus(200);
        $response->assertSee('Taylor');
        $response->assertSee('<p>The name is Taylor.</p>', false);
    }
}

در این مثال، ابتدا از URL /view-test بازدید می کنیم و پاسخ را به متغیر در $response قرار می دهیم. سپس از ()assertStatus استفاده می کنیم تا بفهمیم پاسخ دارای کد موفقیت 200 است.

در خط زیر، از متد assertSee برای آزمایش اینکه آیا صفحه HTML برگشتی حاوی کلمه Taylor است یا نه استفاده کردیم. این assert به طور خودکار از رشته داده شده escape می کند مگر اینکه همانطور که در assert سوم مشاهده می شود به عنوان پارامتر دوم false را ارسال کنید. اگر اجازه escape به رشته داده شود، با تگ <p> به عنوان &lt;p&gt رفتار میشود و نه به عنوان یک تگ HTML.

تست را با دستور زیر اجرا کنید:

./vendor/bin/sail php artisan test ./tests/Feature/ViewTest.php

خروجی:

PASS  Tests\Feature\ViewTest
 ✓ if view contains  taylor

 Tests:  1 passed
 Time:   0.72s

assert های مشابه عبارتند از ()assertSeeInOrder()،assertSeeText، و غیره. جزئیات این assert ها را می توانید در اینجا بیابید.

مرحله 5 - تست پایگاه داده یا دیتابیس در لاراول

تا اینجا، نحوه نوشتن یونیت تست های پایه را مورد بحث قرار دادیم و سپس چند استراتژی برای تست پاسخ‌های HTTP در برنامه‌های کاربردی دنیای واقعی نشان دادیم. بیایید با آزمایش کدی که از پایگاه داده دریافت میکند یا داده ها را در آن قرار میدهد، آن را یک قدم جلوتر ببریم.

ما می دانیم که برای بیشتر برنامه ها، ما نیاز به ذخیره اطلاعات در یک پایگاه داده داریم، بنابراین بسیار مهم است مطمئن شویم که پایگاه داده همانطور که طراحی شده است کار می کند قبل از اینکه برنامه خود را برای مرحله تولید آماده کنیم. برای انجام این کار، اولین قدم تولید برخی داده های فیک در داخل پایگاه داده ما است. 

تولید داده های فیک

Laravel Sail قبلا هنگامی که دستور ./vendor/bin/sail up را اجرا کردیم، از تنظیمات پایگاه داده برای ما مراقبت کرده بود. به طور پیش فرض، لاراول یک مدل کاربر (./app/Models/User.php) و فایل مهاجرت مربوطه (./database/migrations/2014_10_12_000000_create_users_table.php) را در اختیار ما قرار می دهد. در این بخش، از این مدل کاربر برای نشان دادن نحوه آزمایش پایگاه داده در لاراول استفاده خواهیم کرد.

ادامه دهید و مهاجرت ها را به طور مستقیم اجرا کنید. به یاد داشته باشید که ما باید دستور را در لاراول Sail اجرا کنیم:

./vendor/bin/sail php artisan migrate

خروجی:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (56.59ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (30.96ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (32.18ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (63.55ms)

در حال حاضر، پایگاه داده هنوز خالی است، اما می توانیم از یک factory برای تولید برخی داده ها برای تست استفاده کنیم. در اینجا دستور artisan برای تولید یک factory جدید آمده است:

./vendor/bin/sail php artisan make:factory PostFactory

خروجی:

Factory created successfully.

با این حال، لاراول یک مثال برای مدل User در اختیار ما قرار می دهد. فایل ./database/factories/UserFactory.php  را در ویرایشگر متن خود باز کنید و محتویات آن را بررسی کنید:

code ./database/factories/UserFactory.php

database/factories/UserFactory.php/.

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
 */
class UserFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name(),

            'email' => $this->faker->unique()->safeEmail(),

            'email_verified_at' => now(),

            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password

            'remember_token' => Str::random(10),

        ];
    }
    . . .
}

فایل factory به لاراول می گوید که چه نوع داده ای باید فیلد مربوطه را پر کند. در این مثال، فیلدهای نام و ایمیل با استفاده از کتابخانه Faker PHP ایجاد می‌شوند، email_verified_at با زمان فعلی مقداردهی می‌شود، رمز عبور یک رشته رمزگذاری شده است، و memory_token به‌طور تصادفی به‌عنوان رشته‌ای حاوی 10 کاراکتر تولید می‌شود.

اجرای تست های پایگاه داده

برای استفاده از این factory برای تولید داده‌های آزمایشی، باید اطمینان حاصل کنیم که آن را به مدل کاربر متصل می‌کنیم. فایل ./app/Models/User.php را باز کنید و مطمئن شوید که مدل کاربر از HasFactory استفاده می کند: 

app/Models/User.php/.

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    . . .
}

لاراول به طور خودکار وارد database/factories/. می شود و به دنبال نام کلاسی می گردد که با نام مدل با پسوند فکتوری(<model_name>Factory.php)  مطابقت داشته باشد.

در مرحله بعد، زمان آن است که یک تست برای جدول پایگاه داده کاربر ایجاد کنیم. دستور زیر را در ترمینال خود اجرا کنید:

./vendor/bin/sail php artisan make:test DatabaseTest

خروجی:

Test created successfully.

tests/Feature/DatabaseTest.php/. را در ویرایشگر متن خود باز کنید و یک تست جدید برای پایگاه داده کاربر ایجاد کنید:

code ./tests/Feature/DatabaseTest.php

tests/Feature/DatabaseTest.php/.

<?php
namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

use App\Models\User;

class DatabaseTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Test the user database.
     *
     * @return void
     */
    public function test_user_database()
    {
        User::factory()->count(3)->create();

        $this->assertDatabaseCount('users', 3);
    }
}

در این مثال، ما از RefreshDatabase استفاده کردیم تا مطمئن شویم پس از هر تست، پایگاه داده به حالت اولیه برمیگردد. اگر فکر می کنید ضرورتی ندارد، می توانید این خط را کامنت کنید. همچنین باید مدل User را در فایل تست وارد کنیم.

در داخل تابع ()test_user_database، سه رکورد را از طریق factory کاربر که به تازگی ایجاد کرده‌ایم، در جدول کاربران وارد کردیم. سپس از ()assertDatabaseCount استفاده میکنیم تا بررسی کنیم که سه رکورد در جدول کاربران وجود دارد یا نه.

البته، بسیاری از assert های مفید در دسترس ما هستند. به عنوان مثال، ()assertDatabaseHas وجود یک رکورد خاص در جدول را تست می کند و ()assertDatabaseMissing عدم وجود یک رکورد را تضمین می کند.

$this->assertDatabaseHas('users', [
    'email' => 'sally@example.com',
]);

$this->assertDatabaseMissing('users', [
    'email' => 'sally@example.com',
]);

در نهایت، ما می‌توانیم تست پایگاه داده را با استفاده از دستور زیر اجرا کنیم و معلوم کنیم که آن را تایید می‌کند:

./vendor/bin/sail php artisan test tests/Feature/DatabaseTest.php

 PASS  Tests\Feature\DatabaseTest
✓ user database

Tests:  1 passed
Time:   1.44s

مرحله 6 - تست در مرورگر در لاراول با Laravel Dusk

علاوه بر یونیت تست و فیچر تست، تست مرورگر نیز وجود دارد که می تواند در شرایط خاص مفید باشد. این به ما اجازه می دهد تا رفتار کاربر را در یک مرورگر شبیه سازی کنیم، مانند تایپ چیزی در یک فرم یا فشار دادن یک دکمه. برای این کار باید از پکیجی به نام Laravel Dusk استفاده کنیم.

نصب Laravel Dusk

ادامه دهید و پکیج Laravel Dusk را با استفاده از Composer دانلود کنید:

./vendor/bin/sail composer require --dev laravel/dusk

خروجی:

Using version ^6.24 for laravel/dusk
./composer.json has been updated
Running composer update laravel/dusk
. . .
Discovered Package: laravel/dusk
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: spatie/laravel-ignition
. . .
Publishing complete.

Laravel Dusk به گوگل کروم و ChromeDriver وابسته است، و اگر از ابتدا این آموزش را دنبال کردید و از Laravel Sail برای مقداردهی اولیه پروژه خود استفاده کردید، ChromeDriver باید از قبل نصب شده باشد که بتوانیم کانتینر Docker را ایجاد کنیم. می‌توانید این موضوع را با باز کردن فایل docker-compose.yml در پروژه خود تایید کنید و بررسی کنید که آیا کد زیر وجود دارد یا خیر:

docker-compose.yml

. . .
selenium:
    image: 'selenium/standalone-chrome'
    volumes:
        - '/dev/shm:/dev/shm'
    networks:
        - sail
. . .

اگر از Apple Silicon Mac استفاده می کنید، باید به جای آن از ایمیج seleniarm/standalone-chromium استفاده کنید:

docker-compose.yml 

. . .
selenium:
    image: 'seleniarm/standalone-chromium'

    volumes:
        - '/dev/shm:/dev/shm'
    networks:
        - sail
. . .

این تنظیمات اطمینان حاصل می کند که هنگام اجرای دستور  ./vendor/bin/sail up ، تمام اجزای لازم نصب شده اند. اگر قبلا این کار را نکرده اید، باید گوگل کروم را خودتان نصب کنید.

وقتی آماده ادامه کار شدید، تست مرورگر را از طریق دستور artisan زیر انجام دهید. قبل از انجام این کار مطمئن شوید که Laravel Sail در پس زمینه در حال اجرا است.

./vendor/bin/sail dusk

خروجی:

Time: 00:02.588, Memory: 22.00 MB

OK (1 test, 1 assertion)

اگر از ابتدا این آموزش را دنبال نکردید و پروژه لاراول را بدون داکر اجرا می کنید، باید ChromeDriver را با دستور duck:install نصب کنید.

php artisan dusk:install

خروجی:

Dusk scaffolding installed successfully.
Downloading ChromeDriver binaries...
ChromeDriver binaries successfully installed for version 101.0.4951.41.

برای اجرای تست مرورگر بدون Laravel Sail از دستور زیر استفاده کنید و خروجی مانند قبل خواهد بود:

php artisan dusk

نوشتن تست های مرورگر با Laravel Dusk

شما باید یک پوشه Browser را در پوشه tests پیدا کنید، و در داخل Browser، یک فایل ExampleTest.php برای ما ارائه شده است، بنابراین اجازه دهید نگاهی دقیق‌تر بیندازیم:

tests/Browser/ExampleTest.php/.

<?php

namespace Tests\Browser;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class ExampleTest extends DuskTestCase
{
  public function testBasicExample()
    {
        $this->browse(function (Browser $browser) {

            $browser->visit('/')->assertSee('Laravel');

        });

    }
}

این فایل بسیار شبیه به یونیت تست یا پراپرتی تست است، با این تفاوت که ما از متد ()browse برای شبیه سازی یک مرورگر واقعی استفاده می کنیم. URL روت بازدید می شود و سپس از متد ()assertSee برای بررسی وجود کلمه Laravel در صفحه وب استفاده می شود.

ما همچنین می توانیم با Laravel Dusk کارهای چالش برانگیزتری انجام دهیم. در مثال زیر مسیر login/ بازدید شده و فرم موجود در صفحه پر شده است. لاراول فیلد ورودی را با ویژگی name که با ایمیل مقداردی شده است پیدا می‌کند و عبارت 'example@test.com' را تایپ می‌کند و سپس همین کار را برای فیلد رمز عبور قبل از فشار دادن دکمه ورود برای ارسال فرم انجام می‌دهد.

 
$this->browse(function ($browser) use ($user) {
 $browser->visit('/login')
  ->type('email', 'example@test.com')
  ->type('password', 'thisisapassword')
  ->press('Login');
});

Laravel Dusk روش های دیگری را برای تعامل با صفحه وب شما در اختیار ما قرار می دهد، اما من نمی توانم همه آنها را در اینجا فهرست کنم. اگر علاقه مند به کاوش بیشتر هستید، اسناد آنها را مطالعه کنید.

 

مرحله 7 - ماکینگ APIهای خارجی در لاراول

در این قسمت از آموزش به مفهوم ماکینگ و نحوه انجام آن در اپلیکیشن لاراول می پردازیم. گاهی اوقات، زمانی که ما در حال آزمایش کد خود هستیم، می‌خواهیم از اجرای بخشی از کد جلوگیری کنیم تا تست را سریع نگه داریم و از عوارض جانبی جلوگیری کنیم. به عنوان مثال، زمانی که ما در حال آزمایش کدی هستیم که با یک API تعامل دارد، معمولا نمی‌خواهیم درخواستی از API واقعی برای جلوگیری از خراب شدن تست به دلیل شرایط شبکه و در دسترس بودن سرویس ارائه کنیم. ما می توانیم پاسخ API را با متد fake() در چنین مواردی ماکینگ کنیم.

بیایید با ایجاد یک تست جدید شروع کنیم:

./vendor/bin/sail php artisan make:test MockTest

خروجی:

Test created successfully.

سپس، تست ()test_mock_http را به فایل MockTest.php که به تازگی ایجاد کردیم اضافه کنید:

tests/Feature/MockTest.php/.

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

use Illuminate\Support\Facades\Http;


class MockTest extends TestCase
{
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function test_mock_http()
    {
        // This api is supposed to return a list of countries in JSON format,

        // we can mock it so that it only returns Italy.

        Http::fake([

            'https://restcountries.com/v3.1/all' => Http::response(

                [

                    'name' => 'Italy',

                    'code' => 'IT'

                ],

                200

            ),

        ]);


        $response = Http::get('https://restcountries.com/v3.1/all');


        $this->assertJsonStringEqualsJsonString(

            $response->body(),

            json_encode([

                'name' => 'Italy',

                'code' => 'IT'

            ],)

        );

    }
}



توجه داشته باشید که ما از ویو Http لاراول برای ایجاد درخواست های HTTP در اینجا استفاده می کنیم و این مثال API قرار است لیستی از کشورها را در قالب JSON برگرداند. در تست بالا، ما آن را مجبور می‌کنیم تا داده‌های JSON ویژه و یک کد پاسخ 200 را برگرداند، و از متد assertJsonStringEqualsJsonString() برای بررسی صحت آن استفاده می‌کنیم.

این تست را با دستور زیر اجرا کنید:

./vendor/bin/sail php artisan test ./tests/Feature/MockTest.php

خروجی:

 PASS  Tests\Feature\MockTest
✓ mock http

Tests:  1 passed
Time:   0.86s

می‌توانید از این تکنیک برای آزمایش هر قطعه کدی که با برخی API تعامل دارد استفاده کنید تا از درخواست‌های شبکه در آزمایش‌های واحد خود دوری کنید.

مرحله 8 - برنامه لاراول خود را با GitHub Actions تست کنید

در بخش پایانی آموزش، نحوه راه‌اندازی خط لوله یکپارچه‌سازی پیوسته برای آزمایش کد خود با اقدامات GitHub را نشان خواهم داد. قبل از ادامه، مطمئن شوید که Git را روی سیستم خود نصب کرده اید.

ابتدا یک ترمینال جدید باز کنید و یک ریپازیتوری git را در ریشه پروژه خود از طریق دستور زیر مقداردهی کنید:

git init -b main

خروجی:

Initialized empty Git repository in /<path_to_your_project_root_directory>/.git/

تمام فایل های دایرکتوری را به ریپازیتوری لوکال git اختصاص دهید:

git add . && git commit -m "initial commit"

خروجی:

[main 1e1c3e1] initial commit
 83 files changed, 11070 insertions(+)
 create mode 100644 .editorconfig
 create mode 100644 .env.example
 . . .

در مرحله بعد، ما باید این ریپازیتوری لوکال را در GitHub پوش (push) دهیم. یک ریپازیتوری جدید برای پروژه خود در GitHub ایجاد کنید:

URL ریموت را در این ریپازیتوری کپی کنید.

در مرحله بعد، ما باید این ریپازیتوری لوکال را در GitHub پوش کنیم. یک ریپازیتوری جدید برای پروژه خود در GitHub ایجاد کنید:

URL ریموت را در این ریپازیتوری کپی کنید

به ترمینال برگردید و تغییرات خود را به کنترل از راه دور GitHub که با استفاده از دستورات زیر ایجاد کردیم push کنید:

git remote add origin <remote_url>

git branch -M main

git push -u origin main

 خروجی:

Enumerating objects: 108, done.
Counting objects: 100% (108/108), done.
Delta compression using up to 10 threads
Compressing objects: 100% (89/89), done.
Writing objects: 100% (107/107), 71.63 KiB | 6.51 MiB/s, done.
Total 107 (delta 7), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (7/7), done.
To https://github.com/ericnanhu/git-test.git
   eb84310..1e1c3e1  main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

در مرحله بعد، برای ایجاد یک پایپ لاین CI، باید یک دایرکتوری .github/workflows را در دایرکتوری root پروژه خود ایجاد کنیم. GitHub Actions به طور خودکار فایل های ورک فلو را در این فهرست جستجو می کند.

mkdir -p .github/workflows

یک فایل test.yml در دایرکتوری .github/workflows ایجاد کنید و آن را در ویرایشگر متن خود باز کنید:

code ./github/workflows/test.yml

کد زیر را در فایل قرار دهید:

github/workflows/test.yml./.

name: Laravel Test

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  laravel-tests:

    runs-on: ubuntu-latest

    steps:
    - uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e
      with:
        php-version: '8.1'
    - uses: actions/checkout@v3
    - name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Composer Update
      run: composer update
    - name: Install Dependencies
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: Create Database
      run: |
        mkdir -p database
        touch database/database.sqlite
    - name: Execute tests (Unit and Feature tests) via PHPUnit
      env:
        DB_CONNECTION: sqlite
        DB_DATABASE: database/database.sqlite
      run: vendor/bin/phpunit

این فایل yml در اصل مجموعه‌ای از دستورات را تعریف می‌کند که هر بار که درخواست pull را به main branch پوش کنیم یا درخواست می‌کنیم اجرا می‌شوند. هنگامی که چنین رویدادی شناسایی شد، دستورات لیست شده در بخش jobs.laravel-tests.steps به ترتیب توسط GitHub اجرا می شوند. ویژگی runs-on مشخص می‌کند که محیط تست آخرین نسخه اوبونتو خواهد بود و تمام دستورات داخل مراحل دارای یک نام و یک ویژگی اجرا هستند که دستور اجرا را مشخص می‌کند.

مرحله اول PHP 8.1 را در محیط تست نصب می کند و مرحله دوم ریپازیتوری GitHub را بررسی می کند تا گردش کار بتواند به آن دسترسی داشته باشد. در مرحله بعد، اگر فایل .env.example وجود نداشته باشد، در فایل .env کپی می شود و composer به روز می شود و برای نصب وابستگی های لازم استفاده می شود. دستور php artisan key:generate برای تنظیم مقدار APP_KEY در فایل env شما استفاده می شود و تنظیمات دایرکتوری و پایگاه داده لازم در دو مرحله بعدی انجام می شود. در نهایت تست ها از طریق phpunit اجرا می شوند.

ادامه دهید و تغییراتی را در پروژه خود ایجاد کنید، سپس آنها را متعهد کنید و به شاخه اصلی فشار دهید، به طور خودکار این خط لوله را راه اندازی می کند. اگر مشکلی پیش نیاید، همه مشاغل باید موفق باشند. می توانید نتیجه را با مراجعه به تب Actions ریپازیتوری GitHub خود مشاهده کنید.

نتیجه گیری

تست کد شما یک مرحله تغییر ناپذیر در چرخه عمر توسعه نرم افزار است. هنگامی که شما در حال ایجاد یک برنامه لاراول هستید، بهتر است برای هر کنترلر، تست های پراپرتی/یونیت، برای هر جدول پایگاه داده و تست مرورگر برای هر صفحه وب بنویسید. این فرآیند یکپارچگی کد شما را تضمین می کند.

در این آموزش، در مورد اصول اولیه یونیت تست در لاراول را بررسی کردیم. ما نحوه راه‌اندازی محیط‌های آزمایشی مختلف را در فایل پیکربندی PHPUnit phpunit.xml، نحوه ایجاد و اجرای آزمایش‌ها با استفاده از دستورات ترمینال، و نحوه آزمایش کد از طریق assert ها را مطالعه کردیم.

همچنین درباره نحوه آزمایش response ‌های HTTP که برای برنامه‌های کاربردی وب در دنیای واقعی عملی‌تر است، صحبت کردیم و در مورد تست پایگاه داده و نحوه تولید داده‌های فیک برای تست صحبت کردیم. در نهایت، به طور خلاصه تست مرورگر را معرفی کردیم که کاربران واقعی را در یک مرورگر واقعی شبیه‌سازی می‌کند، و مفهوم ماکینگ، که به ما امکان می‌دهد عملکرد یک قطعه کد را نادیده بگیریم تا بتوانیم بخش‌های دیگر برنامه خود را آزمایش کنیم، را بررسی کردیم.

لطفا توجه داشته باشید که این آموزش شامل همه چیز در مورد تست در لاراول نیست، فقط در را برای شروع و یادگیری بیشتر برای شما باز می کند. می توانید اطلاعات بیشتری در مورد تست را در اسناد رسمی لاراول بخوانید.

 

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.