برنامه نویسی

تست برنامه های کاربردی در لاراول – انجمن DEV

## کاوش پیام‌های خطای غیر معمول هنگام اجرای تست‌ها در لاراول

سلام توسعه دهندگان

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

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

امروز بحث خواهیم کرد Error: Test code or tested code did not (only) close its own output buffers.

پیغام خطا Error: کد تست یا کد تست شده (فقط) بافرهای خروجی خود را نبسته است، یک مشکل رایج در تست‌های PHPUnit هنگام استفاده از بافر خروجی است. بافر خروجی یک ویژگی در PHP است که به شما امکان می دهد خروجی یک اسکریپت را ضبط کنید و قبل از ارسال به مرورگر آن را دستکاری کنید.

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

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

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

بنابراین، برای حل این خطا، باید سطوح بافر خروجی را با استفاده از آن بازیابی کنیم ob_get_level(). این به ما امکان می‌دهد بررسی کنیم که آیا بافرهای خروجی باز بسته نشده‌اند یا خیر. سپس محتویات بافر خروجی را با استفاده از آن بازیابی می کنیم ob_get_contents() و بافر را با استفاده از آن پاک کنید ob_end_clean().

توجه به این نکته مهم است که بسیاری از راه حل های آنلاین استفاده از آنها را توصیه می کنند ob_start() در ابتدای آزمون و ob_end_clean() در پایان. با این حال، این همیشه برای موارد آزمایش پیچیده کار نمی کند.

حالا بیایید به قسمت کد نویسی برویم و ببینیم چگونه می توانیم این راه حل را پیاده سازی کنیم.

<?php

namespace Tests\Unit\V1\Admin\Vehicle;

use App\Http\Livewire\Admin\Vehicle\Add;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
use Tests\TestCase;

class VehicleTest extends TestCase
{
    use RefreshDatabase, WithoutMiddleware;



    public function test_create_new_vehicle_entry_with_file_upload()
    {

        ob_start();
        Storage::fake('avatars');

        $user = User::factory()->create();
        $this->actingAs($user);
        Auth::login($user);

        $file = UploadedFile::fake()->image('avatar.jpg');

        Livewire::test(Add::class)
                ->set([
                    'name' => 'Toyota',
                    'reg_num' => 'GD-123-12',
                    'vin_num' => 'kajsy',
                    'status' => true,
                    'home_away' => true,
                    'image' => $file,
                    'transmission' => 'automatic',
                    'price' => '1000',
                    'fuel' => 'petrol',
                    'mileage' => 1000
                ])
                ->call('create')
                ->assertSet('image', $file->name)
                ->assertHasNoErrors(['name', 'reg_num']);
                 Storage::disk('avatars')->assertExists($file->hashName());
                $this->assertAuthenticatedAs($user);
                $this->assertTrue(Auth::check());
                $this->assertDatabaseHas('vehicles', [
                    'name' => 'Toyota',
                    'reg_num' => 'GD-123-12',
                    'vin_num' => 'kajsy',
                    'serviced' => null,
                    'status' => true,
                    'home_away' => true,
                    'transmission' => 'automatic',
                    'price' => 1000,
                    'fuel' => 'petrol',
                ]);
                ob_get_contents();
                ob_end_clean();
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در بلوک کد بالا، ما در حال نوشتن یک آزمایش برای افزودن یک رکورد جدید خودرو به پایگاه داده هستیم. اکنون من عمداً بلوک های کد را اضافه کرده ام تا به طور خاص پرتاب شوند Error: Test code or tested code did not (only) close its own output buffers، که ‘assertSet(‘image’, $file) است.

اجازه دهید هنگام اجرای این آزمایش با وجود درج، نگاهی به کنسول بیندازیم ob_start() و ob_end_clean().

`
1 تست خطرناک وجود داشت:

1) Tests\Unit\V1\Admin\Vehicle\VehicleTest::test_create_new_vehicle_entry_with_file_upload
کد تست یا کد تست شده (فقط) بافرهای خروجی خود را نبست

F:\projects\Laravel\live2\tests\Unit\V1\Admin\Vehicle\VehicleTest.php:21

شکست ها!
تست ها: 1، ادعاها: 1، شکست ها: 1، پرخطر: 1.
`

پیام خطا هنوز به طور واضح بیان نشده است، اکنون می‌خواهم کد را تغییر داده و آزمایش را اجرا کنم.

`
public function test_create_new_vehicle_entry_with_file_upload()
{

    while (ob_get_level() > 0) {
        ob_end_clean();
    }
    Storage::fake('avatars');

    $user = User::factory()->create();
    $this->actingAs($user);
    Auth::login($user);

    $file = UploadedFile::fake()->image('avatar.jpg');

    Livewire::test(Add::class)
            ->set([
                'name' => 'Toyota',
                'reg_num' => 'GD-123-12',
                'vin_num' => 'kajsy',
                'status' => true,
                'home_away' => true,
                'image' => $file,
                'transmission' => 'automatic',
                'price' => '1000',
                'fuel' => 'petrol',
                'mileage' => 1000
            ])
            ->call('create')
            ->assertSet('image', $file->name)
            ->assertHasNoErrors(['name', 'reg_num']);
            Storage::disk('avatars')->assertExists($file);
            $this->assertAuthenticatedAs($user);
            $this->assertTrue(Auth::check());
            $this->assertDatabaseHas('vehicles', [
                'name' => 'Toyota',
                'reg_num' => 'GD-123-12',
                'vin_num' => 'kajsy',
                'serviced' => null,
                'status' => true,
                'home_away' => true,
                'transmission' => 'automatic',
                'price' => 1000,
                'fuel' => 'petrol',
            ]);
            ob_get_contents();
            ob_end_clean();
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

`

I have replaced ob_start() با ob_get_level() در یک عبارت شرطی که راه اندازی می شود ob_end_clean() وقتی از 0 فراتر رفت. بیایید نگاهی به پیام خطا بیندازیم.

`
PS F:\projects\Laravel\live2> ./vendor/bin/phpunit –filter=VehicleTest
PHPUnit 10.0.11 توسط سباستین برگمان و همکاران.

زمان اجرا: PHP 8.2.0
پیکربندی: F:\projects\Laravel\live2\phpunit.xml

F 1/1 (100%)

زمان: 00:01.956، حافظه: 42.00 مگابایت

1 شکست وجود داشت:

1) Tests\Unit\V1\Admin\Vehicle\VehicleTest::test_create_new_vehicle_entry_with_file_upload
ادعای برابری دو رشته ناموفق بود.
— انتظار می رود
+++ واقعی
@@ @@
-‘avatar.jpg’
+’livewire-file:RxzKXRUzs3bLTN9IHbWBFtHgfTLRb4-metaYXZhdGFyLmpwZw==–size=695.jpg’

F:\projects\Laravel\live2\vendor\livewire\livewire\src\Testing\Concerns\MakesAssertions.php:22
F:\projects\Laravel\live2\tests\Unit\V1\Admin\Vehicle\VehicleTest.php:50
F:\projects\Laravel\live2\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:173

شکست ها!
تست ها: 1، ادعاها: 1، شکست ها: 1.
`

اکنون یک پیام خطای واضح دریافت می کنیم که به ما امکان می دهد کد خود را به درستی اشکال زدایی کنیم.

اکنون که درک روشنی از نحوه رسیدگی به آن داریم Error: Test code or tested code did not (only) close its own output buffers موضوع، ما در قسمت بعدی خود عمیق تر به موضوع اشکال زدایی خواهیم پرداخت. ما برخی از ابزارها و تکنیک‌های ضروری را که هر توسعه‌دهنده‌ای باید در جعبه ابزار خود برای عیب‌یابی سریع و مؤثر مشکلات داشته باشد، پوشش می‌دهیم. گوش به زنگ باشید!

حتما من را در توییتر، github، showwcase در @rebelnii دنبال کنید و در YouTube من مشترک شوید

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا