24 β Testlash (Testing)¶
β¬ οΈ Oldingi: 23 β Xavfsizlik Β· π Kitob boshi Β· Keyingi: 25 β Performance va deploy β‘οΈ
Bu bobda: komponentlaringizni qo'lda emas, avtomatik sinab ko'rishni o'rganamiz. Livewire'ning maxsus test API'si bilan komponentni "yashirin brauzer" ichida ishga tushiramiz: xususiyatlarini o'rnatamiz (
set), metodlarini chaqiramiz (call) va natijani tasdiqlaymiz (assertSee,assertSet,assertHasErrors,assertDispatchedva boshqalar). Counter, forma, validatsiya, event va avtorizatsiya testlarini yozamiz; Pest va PHPUnit sintaksislarini ko'ramiz; va nima uchun muhim mantiqni doim test bilan qo'riqlash kerakligini tushunamiz.
Nega umuman test yozish kerak?¶
Tasavvur qiling, siz katta ilova yaratdingiz: 30 ta komponent, ularda forma, validatsiya, hisob-kitob, baza bilan ishlash. Bir kun kelib kichik bir o'zgartirish kiritasiz β masalan, validatsiya qoidasini yangilaysiz. Endi savol: bu o'zgartirish boshqa 30 ta komponentdan birortasini buzdimi yoki yo'qmi?
Buni qo'lda tekshirish degani β brauzerni ochib, har bir sahifaga kirib, har bir tugmani bosib, har bir formani to'ldirib, ko'z bilan ko'rib chiqishdir. Bu:
- charchatadi β har safar o'nlab qadam;
- vaqt yeydi β har bir kichik o'zgartirishdan keyin yarim soat tekshiruv;
- xato qoldiradi β odam toliqadi, "bu joyni tekshirgandirman" deb o'tkazib yuboradi.
Aynan shu yerda avtomatik test yordam beradi. Test β bu kod parchasi bo'lib, u sizning komponentingizni o'zi ishga tushiradi, o'zi tugma "bosadi", o'zi forma "to'ldiradi" va natija kutilgandek bo'lganini o'zi tekshiradi. Siz bir marta yozasiz, keyin minglab marta bir buyruq bilan ishga tushirasiz.
Hayotiy o'xshatish β avtomatik nazoratchi. Zavodni tasavvur qiling. Konveyerdan chiqayotgan har bir mahsulotni odam qo'lda tekshirsa β charchaydi, ba'zi nuqsonlarni o'tkazib yuboradi. Shuning uchun zavodlar avtomatik nazoratchi (sensor) o'rnatadi: u har bir mahsulotni bir xil aniqlik bilan, charchamasdan, 24 soat tekshiradi. Nuqsonli mahsulot chiqsa β darhol signal beradi. Test ham aynan shunday avtomatik nazoratchi: sizning kodingizni har safar bir xil aniqlik bilan tekshiradi va biror narsa buzilsa β darhol "qizil" signal beradi.
Testning eng katta foydasi β regress himoyasi ("regression" β eski, ishlab turgan narsaning yangi o'zgartirishdan keyin buzilishi). Yangi kod yozganingizda eski testlarni qayta ishga tushirasiz: agar hammasi yashil bo'lsa β siz hech narsani buzmaganingizga ishonchingiz komil. Bu ishonch β tez va qo'rqmasdan rivojlanishning kalitidir.
Eslatma β test bu vaqt isrofi emas, sarmoya
Boshida "test yozishga vaqtim yo'q" tuyulishi mumkin. Lekin amalda aksincha: test bir marta yoziladi, keyin har bir o'zgartirishda sizni soatlab qo'lda tekshirishdan qutqaradi. Eng muhimi β yarim tunda "ilovam buzildi!" degan qo'ng'iroqdan saqlaydi.
Livewire test API asoslari¶
Oddiy Laravel testida biz sahifani HTTP orqali ochamiz ($this->get('/counter')). Lekin Livewire komponenti β bu shunchaki sahifa emas: uning holati bor (xususiyatlar), amallari bor (metodlar), u interaktiv. Shuning uchun Livewire o'zining maxsus test yordamchisini beradi β Livewire::test(...).
Avval uni import qilamiz:
So'ng komponentni "yashirin" ishga tushiramiz. Komponentni ikki xil ko'rsatish mumkin β klass bo'yicha yoki nom bo'yicha:
// klass bo'yicha (klass-komponentlar uchun)
Livewire::test(\App\Livewire\Counter::class);
// nom bo'yicha (SFC β single-file komponentlar uchun ham qulay)
Livewire::test('counter');
Hayotiy o'xshatish β uchuvchi trenajyori. Haqiqiy samolyotni uchirib sinab ko'rish qimmat va xavfli. Shuning uchun uchuvchilar trenajyor (simulyator) ichida mashq qiladi: bu xuddi haqiqiy kabina, lekin yerda, xavfsiz.
Livewire::test(...)β bu sizning komponentingiz uchun aynan shunday trenajyor: brauzer ochmasdan, server jonli ishlamasdan, komponent xuddi haqiqatda ishlagandek ishlaydi va siz har bir tugmasini bemalol sinab ko'rasiz.
Livewire::test(...) chaqirig'i test obyektini qaytaradi. Endi shu obyektda zanjir (chain) ko'rinishida amallarni ketma-ket bajaramiz: holatni o'rnatamiz, metod chaqiramiz, natijani tekshiramiz. Har bir metod yana o'sha obyektni qaytaradi β shuning uchun ularni -> bilan uzluksiz ulayveramiz (buni fluent interface β "ravon interfeys" deyiladi).
Asosiy zanjir: set β call β assert¶
Eng ko'p ishlatiladigan uchta amalni ko'raylik. Misol uchun 03-bobdagi tanish counter komponentini olamiz:
{{-- resources/views/components/β‘counter.blade.php --}}
<?php
use Livewire\Component;
new class extends Component
{
public int $count = 0;
public function increment(): void
{
$this->count++;
}
};
?>
<div>
<h1>Hisob: {{ $count }}</h1>
<button wire:click="increment">+</button>
</div>
Endi bu komponent uchun test yozamiz. Uch amalni eslab qoling:
->set('xususiyat', qiymat)β komponent xususiyatiga qiymat beradi (xuddi foydalanuvchi maydonni to'ldirgandek).->call('metod')β komponent metodini chaqiradi (xuddi foydalanuvchi tugmani bosgandek).->assertSee('matn')β render qilingan HTML'da shu matn borligini tasdiqlaydi.
use Livewire\Livewire;
Livewire::test('counter')
->assertSee('Hisob: 0') // boshlang'ich holatda 0 ko'rinadi
->call('increment') // "+" tugmasini "bosamiz"
->assertSee('Hisob: 1') // endi 1 ko'rinishi kerak
->set('count', 5) // hisobni to'g'ridan-to'g'ri 5 ga o'rnatamiz
->call('increment') // yana bir marta oshiramiz
->assertSee('Hisob: 6'); // 6 ko'rinishi kerak
Bu zanjirni o'qish β bu komponent bilan foydalanuvchining suhbatini o'qishdek: "sahifa ochildi, 0 ko'rindi β plyusni bosdim β 1 bo'ldi β hisobni 5 ga o'zgartirdim β yana bosdim β 6 bo'ldi". Test aynan shu ssenariyni avtomatik takrorlaydi.
Tasdiqlangan. Bu test jonli Laravel 12 + Livewire v4.3.1 loyihada o'tdi (3 ta test, 9 ta assertion).
Livewire::test('counter')->assertSee('Hisob: 0')->call('increment')->assertSee('Hisob: 1')->set('count', 5)->call('increment')->assertSee('Hisob: 6')β yashil.
Maslahat β set va call ning farqini eslang
set('count', 5) β holatni to'g'ridan-to'g'ri o'zgartiradi (foydalanuvchi wire:model orqali maydon to'ldirgani kabi). call('increment') β metodni ishga soladi (foydalanuvchi wire:click tugmasini bosgani kabi). Ko'pincha avval set bilan kerakli holatni tayyorlab, keyin call bilan amalni ishga tushiramiz va assert bilan natijani tekshiramiz.
Assertion'lar: nimani tekshirish mumkin?¶
Assertion ("tasdiqlash") β bu testning yuragi. U "men shunday bo'lishini kutaman" deydi; agar haqiqat boshqacha bo'lsa, test yiqiladi (qizil). Livewire juda boy assertion to'plamini beradi. Mana eng muhimlari:
| Assertion | Nimani tekshiradi |
|---|---|
assertSee('matn') |
Render qilingan HTML'da matn bor |
assertDontSee('matn') |
HTML'da matn yo'q |
assertSet('count', 6) |
Xususiyat qiymati aynan shunday |
assertHasErrors(['title' => 'required']) |
Validatsiya xatosi bor (maydon + qoida) |
assertHasNoErrors() |
Hech qanday validatsiya xatosi yo'q |
assertDispatched('saved') |
Shu nomli event yuborilgan |
assertNotDispatched('saved') |
Event yuborilmagan |
assertRedirect('/posts') |
Komponent shu manzilga yo'naltirdi |
assertStatus(200) |
Javob statusi shunday (200 β OK, 403 β taqiqlangan) |
assertForbidden() |
Status 403 (taqiqlangan) |
assertViewHas('posts') |
Blade shablonga shu o'zgaruvchi uzatilgan |
Ularning ko'pini quyida amalda ishlatamiz. Hozircha asosiy g'oyani eslab qoling: har bir assertion β bu bitta savol ("hisob 6 mi? xato bormi? event yuborildimi?"), va test shu savollarning hammasiga "ha" javobini olganda yashil bo'ladi.
Eslatma β assertSet va assertSee farqi
assertSet('count', 6) β komponentning ichki holatini (xususiyat qiymatini) tekshiradi. assertSee('Hisob: 6') β foydalanuvchi ekranda ko'radigan HTML'ni tekshiradi. Ko'pincha ikkalasini birga ishlatamiz: holat to'g'ri va u to'g'ri ko'rinyaptimi.
Forma testi: saqlash va validatsiya¶
Endi haqiqiy loyihaga yaqinroq misol β forma. Quyidagi komponent post yaratadi: u sarlavha va matnni validatsiya qiladi, bazaga saqlaydi va event yuboradi (bu naqshlarni 09-formalar, 10-validatsiya va 18-events boblarida ko'rgan edik):
{{-- resources/views/components/β‘post-create.blade.php --}}
<?php
use App\Models\Post;
use Livewire\Component;
use Livewire\Attributes\Validate;
new class extends Component
{
#[Validate('required|min:3')]
public string $title = '';
#[Validate('required')]
public string $body = '';
public function save(): void
{
$this->validate();
$post = Post::create([
'title' => $this->title,
'body' => $this->body,
]);
$this->dispatch('post-created', id: $post->id);
$this->reset();
}
};
?>
<div>
<form wire:submit="save">
<input type="text" wire:model="title" placeholder="Sarlavha">
@error('title') <span>{{ $message }}</span> @enderror
<textarea wire:model="body" placeholder="Matn"></textarea>
@error('body') <span>{{ $message }}</span> @enderror
<button type="submit">Saqlash</button>
</form>
</div>
"Baxtli yo'l": forma to'g'ri to'ldirilganda¶
Avval muvaffaqiyatli holatni ("happy path" β hammasi to'g'ri bo'lgan ssenariy) tekshiramiz: forma to'ldiriladi, saqlanadi, xato bo'lmaydi, ma'lumot bazaga tushadi:
use Livewire\Livewire;
use Illuminate\Foundation\Testing\RefreshDatabase;
class PostCreateTest extends TestCase
{
use RefreshDatabase; // har test uchun toza baza
public function test_post_is_saved(): void
{
Livewire::test('post-create')
->set('title', 'Mening birinchi postim')
->set('body', 'Bu post matni.')
->call('save')
->assertHasNoErrors(); // validatsiya o'tdi
// ma'lumot rostdan bazaga tushdimi?
$this->assertDatabaseHas('posts', [
'title' => 'Mening birinchi postim',
]);
}
}
Bu yerda ikki yangi narsa bor:
use RefreshDatabase;β bu trait (tayyor xususiyatlar to'plami) har bir test boshlanishidan oldin bazani toza holatga keltiradi. Shunda bitta test ikkinchisiga ta'sir qilmaydi (testlar bir-biridan mustaqil bo'lishi shart). Testlarda odatda alohida, xotiradagi (in-memory) SQLite bazasi ishlatiladi β tez va xavfsiz.$this->assertDatabaseHas('posts', [...])β bu Laravel'ning (Livewire emas) assertion'i: posts jadvalida shunday yozuv borligini tekshiradi. Ya'ni "forma rostdan ham bazaga yozdimi?" degan savolga javob beradi.
"Qora yo'l": forma bo'sh bo'lganda¶
Endi xato holatini tekshiramiz: forma bo'sh yuborilsa, validatsiya xato berishi va baza bo'sh qolishi kerak:
public function test_empty_form_shows_errors(): void
{
Livewire::test('post-create')
->set('title', '')
->set('body', '')
->call('save')
->assertHasErrors(['title' => 'required', 'body' => 'required']);
$this->assertDatabaseCount('posts', 0); // hech narsa saqlanmadi
}
assertHasErrors(['title' => 'required']) β title maydonida required qoidasi bo'yicha xato borligini tasdiqlaydi. Bu juda kuchli: nafaqat "xato bormi" balki "qaysi maydonda, qaysi qoida bo'yicha" ekanini ham tekshiradi. Qisqaroq variant β faqat maydon nomini berish: assertHasErrors('title').
min qoidasini ham alohida tekshirsak bo'ladi:
public function test_short_title_fails(): void
{
Livewire::test('post-create')
->set('title', 'Hi') // 3 belgidan kam
->set('body', 'matn')
->call('save')
->assertHasErrors(['title' => 'min']); // min:3 qoidasi buzildi
}
Tasdiqlangan. Yuqoridagi uchta forma testi (saqlash, bo'sh forma, qisqa sarlavha) jonli Livewire v4.3.1 loyihada o'tdi.
assertHasNoErrors,assertHasErrors(['title' => 'min']),assertDispatched('post-created'),assertDatabaseHas,assertDatabaseCountβ barchasi yashil.
Maslahat β har doim ikki tomonni test qiling
Yaxshi formaning ikki yuzi bor: to'g'ri to'ldirilganda ishlashi va noto'g'ri to'ldirilganda to'xtatishi. Faqat "baxtli yo'l" ni test qilsangiz, validatsiyangiz buzilib qolsa ham sezmaysiz. Doim ikkala ssenariyni test qiling β bu testning eng katta qiymati.
Event testi: yuborilganini tekshirish¶
18-bobda ko'rganimizdek, event β bu komponentlar orasidagi "ko'rinmas" aloqa. Aynan ko'rinmas bo'lgani uchun uni test bilan qo'riqlash juda muhim. Yuqoridagi post-create komponenti saqlangach post-created eventini yuboradi β buni tekshiramiz:
public function test_event_is_dispatched_after_save(): void
{
Livewire::test('post-create')
->set('title', 'Yangi post')
->set('body', 'Matn')
->call('save')
->assertDispatched('post-created'); // event yuborildimi?
}
assertDispatched('post-created') β shu nomli event yuborilganini tasdiqlaydi. Parametrini ham tekshirish mumkin:
Aksincha, yuborilmaganini tekshirish ham foydali β masalan, validatsiya yiqilganda event chiqmasligi kerak:
public function test_no_event_when_validation_fails(): void
{
Livewire::test('post-create')
->set('title', '') // bo'sh -> validatsiya yiqiladi
->call('save')
->assertHasErrors('title')
->assertNotDispatched('post-created'); // event CHIQMASLIGI kerak
}
Bu test juda qimmatli: u "forma noto'g'ri bo'lsa, ro'yxat bekorga yangilanmaydi" degan muhim mantiqni qo'riqlaydi.
Avtorizatsiya testi: kim nima qila oladi?¶
23-bobda bilib oldikki, har bir xavfli amalda avtorizatsiya (kim ruxsat etilgan) tekshirilishi shart. Testning eng muhim vazifalaridan biri β bu himoyaning rostdan ishlayotganini tasdiqlash.
Avval foydalanuvchi sifatida "kirib olamiz" β buning uchun Laravel'ning $this->actingAs($user) metodi xizmat qiladi. U "shu testning davomida men aynan shu foydalanuvchiman" deydi:
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
class SecretTest extends TestCase
{
use RefreshDatabase;
public function test_admin_can_run_action(): void
{
$admin = User::factory()->create(); // birinchi user -> id = 1
$this->actingAs($admin); // shu user sifatida kiramiz
Livewire::test('secret')
->call('deleteEverything')
->assertStatus(200); // ruxsat berildi (OK)
}
}
Endi boshqa foydalanuvchi shu amalni chaqirsa, 403 (taqiqlangan) qaytishini tekshiramiz:
public function test_other_user_is_forbidden(): void
{
User::factory()->create(); // id = 1 (admin)
$other = User::factory()->create(); // id = 2 (oddiy foydalanuvchi)
$this->actingAs($other); // oddiy user sifatida kiramiz
Livewire::test('secret')
->call('deleteEverything')
->assertForbidden(); // 403 β taqiqlangan!
}
Bu yerda tekshirilayotgan komponent quyidagicha (faqat id = 1 ruxsat etilgan):
{{-- resources/views/components/β‘secret.blade.php --}}
<?php
use Livewire\Component;
new class extends Component
{
public function deleteEverything(): void
{
abort_unless(auth()->id() === 1, 403); // faqat admin
// ... haqiqiy o'chirish mantig'i ...
}
};
?>
<div>
<button wire:click="deleteEverything">Hammasini o'chirish</button>
</div>
assertForbidden() β javob statusi 403 ekanini tekshiradi (assertStatus(403) ning qisqasi). Haqiqiy loyihada abort_unless(...) o'rniga ko'pincha Policy ishlatasiz: $this->authorize('delete', $post) β bu ham ruxsat bo'lmasa 403 beradi va test aynan shu tarzda uni ushlaydi.
Tasdiqlangan. Avtorizatsiya testlari (admin β 200, boshqa foydalanuvchi β 403) jonli loyihada o'tdi.
actingAs,assertStatus(200)vaassertForbidden()β yashil.
Xavfsizlik β avtorizatsiyani DOIM test qiling
Xavfsizlik mantig'i β bu testning eng muhim mijozi. "Boshqa foydalanuvchi bu amalni qila olmasligi kerak" degan testni yozmasangiz, kelajakda kimdir kodni o'zgartirib himoyani tasodifan olib tashlasa β siz buni hech qachon sezmaysiz, faqat ma'lumot o'g'irlangach bilasiz. Har bir authorize chaqirig'i uchun "ruxsat berilgan" va "taqiqlangan" β ikki testni yozing.
Pest va PHPUnit: ikki sintaksis¶
Test kodini yozishning ikki ommabop uslubi bor. Mazmun bir xil β faqat tashqi ko'rinishi farq qiladi.
PHPUnit uslubi (klass va metodlar)¶
An'anaviy va eng keng tarqalgan uslub. Har test β bu test_ bilan boshlanadigan metod, hammasi bir klass ichida:
<?php
namespace Tests\Feature;
use Livewire\Livewire;
use Tests\TestCase;
class CounterTest extends TestCase
{
public function test_it_increments(): void
{
Livewire::test('counter')
->call('increment')
->assertSet('count', 1);
}
}
Pest uslubi (qisqa va o'qishli)¶
Pest β bu PHPUnit ustiga qurilgan, juda qisqa va o'qishli zamonaviy test asbobi. Bu yerda klass yo'q β har test it(...) yoki test(...) funksiyasi:
<?php
use Livewire\Livewire;
it('increments', function () {
Livewire::test('counter')
->call('increment')
->assertSet('count', 1);
});
it('increments', ...) o'qilganda deyarli ingliz tilidagi jumlaga o'xshaydi: "it increments" ("u oshiradi"). Yangi Laravel loyihalari ko'pincha Pest bilan keladi.
Eslatma β qaysi birini tanlash?
Ikkalasi ham bir xil ishlaydi va bir xil Livewire assertion'larini qo'llaydi β Livewire::test(...)->set(...)->call(...)->assertSee(...) zanjiri hech o'zgarmaydi. Loyihangizda qaysi biri o'rnatilgan bo'lsa β o'shani ishlating. Yangi loyiha boshlasangiz, ko'pchilik bugun Pest ni afzal ko'radi (qisqaroq, chiroyliroq). Bu kitobdagi misollar ikkala uslubda ham bemalol ishlaydi.
Testlarni ishga tushirish ikkalasida ham bir xil β terminalda:
To'liq misol: CRUD testlari¶
Endi hamma bilimni birlashtiramiz. 16-bobda to'liq CRUD (Create-Read-Update-Delete) komponentini qurgan edik. Bunday komponentni qanday test qilamiz? To'rt amalning to'rttasini ham alohida sinaymiz. Mana CRUD test rejasi (PHPUnit uslubida):
<?php
namespace Tests\Feature;
use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;
class PostCrudTest extends TestCase
{
use RefreshDatabase;
// CREATE β yaratish
public function test_can_create_post(): void
{
Livewire::test('post-manager')
->set('title', 'Yangi maqola')
->set('body', 'Maqola matni')
->call('save')
->assertHasNoErrors();
$this->assertDatabaseHas('posts', ['title' => 'Yangi maqola']);
}
// VALIDATE β bo'sh forma to'xtatilishi
public function test_create_requires_title(): void
{
Livewire::test('post-manager')
->set('title', '')
->call('save')
->assertHasErrors(['title' => 'required']);
}
// READ β ro'yxat ko'rinishi
public function test_shows_existing_posts(): void
{
Post::create(['title' => 'Salom dunyo', 'body' => '...']);
Livewire::test('post-manager')
->assertSee('Salom dunyo');
}
// UPDATE β tahrirlash
public function test_can_update_post(): void
{
$post = Post::create(['title' => 'Eski', 'body' => '...']);
Livewire::test('post-manager')
->call('edit', $post->id) // tahrirga olish
->set('title', 'Yangilangan')
->call('save')
->assertHasNoErrors();
$this->assertDatabaseHas('posts', [
'id' => $post->id,
'title' => 'Yangilangan',
]);
}
// DELETE β o'chirish
public function test_can_delete_post(): void
{
$post = Post::create(['title' => 'O\'chiriladi', 'body' => '...']);
Livewire::test('post-manager')
->call('delete', $post->id)
->assertDontSee('O\'chiriladi'); // ro'yxatdan yo'qoldi
$this->assertDatabaseMissing('posts', ['id' => $post->id]);
}
}
Diqqat qiling, har bir test:
- Tayyorlaydi (arrange) β kerakli holatni yaratadi (masalan, bazaga post qo'shadi yoki maydonni to'ldiradi).
- Bajaradi (act) β bitta amalni ishga tushiradi (
call('delete', $id)). - Tekshiradi (assert) β natija kutilgandek bo'lganini tasdiqlaydi.
Bu Arrange-Act-Assert ("Tayyorla-Bajar-Tekshir") naqshi β barcha yaxshi testlarning skeleti. Har bir test bitta narsani tekshiradi: shunda yiqilganda nima buzilganini darrov bilasiz.
Maslahat β call('edit', $id) β bu parametrli metod chaqirig'i
call('delete', $post->id) β bu delete($id) metodini $post->id argumenti bilan chaqiradi. Bu xuddi Blade'dagi wire:click="delete({{ $post->id }})" ning test ekvivalenti. Bir nechta argument ham mumkin: call('move', $id, 'arxiv').
Test piramidasi: qancha va qaysi turdan?¶
Testlarning bir necha turi bor va ularning nisbati muhim. Buni test piramidasi bilan tasvirlaymiz:
- Pastda (eng ko'p) β Unit testlar. Eng kichik bo'lakni alohida sinaydi (masalan, bitta yordamchi funksiya: narxni hisoblash). Juda tez, juda ko'p yoziladi.
- O'rtada (o'rtacha) β Feature / komponent testlari. Bir necha qism birga ishlashini sinaydi.
Livewire::test(...)aynan shu darajada turadi β u komponentni, uning holatini, render'ini, baza bilan aloqasini birga sinaydi. Bu Livewire ilovasi uchun eng qimmatli test turi. - Tepada (eng kam) β E2E (uchma-uch) testlar. Butun ilovani haqiqiy brauzerda, foydalanuvchi ko'zi bilan sinaydi (masalan Laravel Dusk). Eng realistik, lekin eng sekin va eng mo'rt (tez buziladi). Shuning uchun ulardan kam yoziladi β faqat eng muhim ssenariylar uchun.
Hayotiy o'xshatish β uy qurilishini tekshirish. Avval har bir g'ishtni alohida tekshirasiz (unit) β bu tez va arzon, shuning uchun hammasini tekshirasiz. Keyin devorni yig'ib mustahkamligini sinaysiz (feature/komponent). Va nihoyat, butun uyga kirib yashab ko'rasiz (E2E) β eng ishonchli, lekin uzoq va qimmat, shuning uchun bir-ikki marta. Pastdan tepaga: ko'pdan ozga, tezdan sekinga.
Xulosa: Livewire ilovangizda asosiy kuchingizni Livewire::test(...) komponent testlariga sarflang. Ular tez, ishonchli va sizning biznes mantig'ingizning katta qismini qamrab oladi.
TDD: avval test, keyin kod¶
TDD (Test-Driven Development β "test boshqaradigan dasturlash") β bu maxsus uslub: avval test yoziladi, keyin uni o'tkazadigan kod yoziladi. Tartibi shunday:
- Qizil: hali kod yo'q test yoz β u, albatta, yiqiladi (qizil).
- Yashil: testni o'tkazadigan eng oddiy kodni yoz β test yashil bo'ldi.
- Yaxshila (refactor): kodni tozalab, chiroyli qilib qayta yoz β test baribir yashil turaversin.
So'ng keyingi xususiyat uchun qaytadan: qizil β yashil β yaxshila.
Hayotiy o'xshatish β avval xarita, keyin yo'l. TDD β bu "qayerga borishimni avval xaritaga belgilab, keyin yo'lga chiqish" kabi. Test β bu sizning xaritangiz: "kod oxirida nima qilishi kerak" ni aniq belgilaydi. Keyin shunchaki xaritaga ergashasiz. Bu adashishdan, ortiqcha kod yozishdan saqlaydi.
TDD majburiy emas β boshlovchi uchun avval kod yozib, keyin test qo'shish ham mutlaqo to'g'ri. Lekin TDD ning bir buyuk afzalligi bor: u sizni kod yozishdan oldin "bu komponent aniq nima qilishi kerak?" deb o'ylashga majbur qiladi. Bu ko'pincha yaxshiroq dizaynga olib keladi.
Maslahat β muhim mantiqni DOIM test bilan qo'riqlang
Hamma narsani test qilish shart emas (oddiy {{ $title }} ko'rsatishni test qilish ortiqcha). Lekin muhim mantiq β pul hisob-kitobi, avtorizatsiya, validatsiya, ma'lumotni o'zgartirish β doim test bilan qoplanishi kerak. Qoida sodda: "agar bu buzilsa, jiddiy muammo bo'ladimi?" β javob "ha" bo'lsa, test yozing. Bu testlar sizning ilovangizning eng qimmatli qismini har o'zgarishdan keyin sodiq qo'riqchidek himoya qiladi.
Xulosa¶
- Test β bu avtomatik nazoratchi. Qo'lda tekshirish charchatadi va xato qoldiradi; test esa charchamasdan, bir xil aniqlik bilan kodingizni har safar sinaydi va regress (eski narsaning buzilishi) dan himoya qiladi.
- Livewire test API:
use Livewire\Livewire;so'ngLivewire::test(Counter::class)yoki nom bilanLivewire::test('counter')β komponentni "trenajyorda" ishga tushiradi. - Asosiy zanjir:
->set('xususiyat', qiymat)(holat o'rnat),->call('metod')(amal ishga tushir),->assertSee('matn')(natija tekshir). Hammasini->bilan ravon ulaymiz. - Boy assertion to'plami:
assertSee/assertDontSee,assertSet,assertHasErrors/assertHasNoErrors,assertDispatched/assertNotDispatched,assertRedirect,assertStatus/assertForbidden,assertViewHas. - Forma testi: ikki tomon β to'g'ri to'ldirilganda
assertHasNoErrors+assertDatabaseHas; bo'sh bo'lgandaassertHasErrors([...]).use RefreshDatabase;har test uchun toza baza beradi. - Event testi:
assertDispatched('post-created')(yuborildi),assertNotDispatched(...)(yuborilmadi β validatsiya yiqilganda event chiqmasligini qo'riqlaydi). - Avtorizatsiya testi:
$this->actingAs($user)bilan kirib, ruxsatliniassertStatus(200), taqiqlanganniassertForbidden()(403) bilan tekshiring. Xavfsizlik mantig'ini albatta test qiling (23-bob). - Pest yoki PHPUnit: sintaksis farqi (
it('...', fn)vstest_metod()), lekin Livewire zanjiri ikkalasida bir xil. - Test piramidasi: ko'p unit, o'rtacha feature/komponent (Livewire shu yerda β eng qimmatli), kam E2E.
- Muhim mantiqni doim test qiling: pul, avtorizatsiya, validatsiya, ma'lumot o'zgarishi β "buzilsa jiddiy bo'ladimi?" javobi "ha" bo'lsa β test yozing.
Amaliy mashqlar¶
-
Counter testi (oson).
counterkomponenti uchun test yozing: boshlang'ichassertSee('Hisob: 0'), keyincall('increment')ikki marta vaassertSet('count', 2). So'ngset('count', 10)->call('decrement')->assertSee('Hisob: 9'). Testniphp artisan test --filter=...bilan ishga tushirib, yashil bo'lishini ko'ring. Yo'naltirish:Livewire::test('counter')dan boshlang. -
Forma validatsiyasi (osonβo'rta). 10-bobdagi yoki o'zingiz yaratgan forma komponenti uchun ikki test yozing: (a) to'g'ri to'ldirilganda
assertHasNoErrors(); (b) bo'sh yuborilgandaassertHasErrors(['title' => 'required']). Yo'naltirish:use RefreshDatabase;ni unutmang, agar saqlash bazaga yozsa. -
Event tekshiruvi (o'rta). 18-bobdagi
task-createdeventini yuboradigan formani test qiling:set('title', '...')->call('save')->assertDispatched('task-created'). Keyin teskari holatni qo'shing: bo'sh forma yuborilgandaassertNotDispatched('task-created')ekanini tekshiring. Yo'naltirish: validatsiya yiqilsa event chiqmasligi kerak. -
CRUD to'liq qamrov (o'rtaβqiyin). 16-bobdagi CRUD komponentingiz uchun to'rt test yozing: create (
assertDatabaseHas), read (assertSeemavjud yozuv), update (call('edit', $id)βsetβsaveβassertDatabaseHasyangilangan qiymat), delete (call('delete', $id)βassertDatabaseMissing). Har biri bitta amalni tekshirsin. Yo'naltirish: Arrange-Act-Assert tartibiga rioya qiling. -
Avtorizatsiya himoyasi (qiyin β fikrlash uchun). Avtorizatsiya qiladigan komponent yozing (masalan, faqat post egasi uni o'chira oladi). Ikki test yozing: egasi
actingAsbilancall('delete', $id)qila olsin (assertStatus(200)yokiassertHasNoErrors); boshqa foydalanuvchi esaassertForbidden()olsin. Keyin o'ylab ko'ring: agar kelajakda kimdirauthorizeqatorini xatoga o'chirib qo'ysa, qaysi test buni darhol ushlaydi? Bu nima uchun ko'z bilan tekshirishdan ishonchliroq? (Maslahat: avtorizatsiya testi bo'limini va 23-bobni qayta o'qing.)
β¬ οΈ Oldingi: 23 β Xavfsizlik Β· π Kitob boshi Β· Keyingi: 25 β Performance va deploy β‘οΈ