Back

Testování


Úvod

Pro automatizované testování používáme framework Pest kvůli jeho mnoha výhodám. Pest se soustředí na jednoduchost a psaní testů je s ním opravdu zábava.

Navíc má také lepší asserty, pěknou syntaxi a skvělou dokumentaci.

Příkaz pro vytvoření: php artisan make:test Actions/VerifyUserActionTest

1it('has a welcome page', function() {
2 $response = $this->get('/');
3 
4 expect($response->status())->toBe(200);
5});

Proč psát testy?

  • Kvalita kódu - psání testů Vás donutí nad kódem přemýšlet
  • Odchytávání bugů - testy dokážou odhalit některé chyby před tím, než se dostanou na produkci
  • Úspora času - v dlouhodobém měřítku testy snižují potřeby manuálního testování
  • Větší jistota - je snazší provádět změny v kódu a přidávat nové funkce, jelikož je malé riziko zničení funkcionality

Kdy psát testy?

Každá vytvořená třída obsahující nějakou logiku by měla mít také test.

Co by mělo být testováno?

  • Logika v kódu (akce, support třídy, joby…)
  • Livewire komponenty / Controllery
  • Routy

Jak psát testy?

Na většině projektů píšeme pouze Feature testy. Nicméně u některých složitých projektů je důležité zahrnout také Unit testy.

Při psaní testů je důležité zahrnout několik scénářů, aby se pokrylo co nejvíce možných případů. Kromě toho by testy také měly obsahovat pouze asserty, která jsou přímo související s testovanou třídou nebo funkcí. Tím se předejde redundanci a zlepší se celková čitelnost testů.

Pro tip: Udržujte pokrytí testy co nejvyšší, mělo by to být alespoň 70 %.

Helpery

Helpery mohou snížit duplicitu v kódu a zlepšit čitelnost testů. Pomocí Pest hooků můžete připravovat/čistit data před/po každém/všech spuštění testů. Kromě toho můžete vytvářet vlastní metody, které lze použít v několika testech.

Pest hooky

  • beforeEach() - Připraví něco před každým jednotlivým spuštění testu…
  • afterEach() - Vyčistí testovací data po každém jednotlivém spuštění testu…
  • beforeAll() - Připraví něco před spuštěním všech testů…
  • afterAll() - Vyčistí testovací data po spuštění všech testů…

Vlastní metody

Tyto metody lze napsat v jednom testovacím souboru nebo přímo v souboru Pest.php, aby byly globálně přístupné.

Příklad lokálního helperu v konkrétním testu:

1function asAdmin(): User
2{
3 $user = User::factory()->create(['admin' => true]);
4 
5 return test()->actingAs($user);
6}
7 
8it('can manage users', function () {
9 asAdmin()->get('/users')->assertOk();
10})

Příklad globálního helperu v Pest.php:

1function mockPayments(): object
2{
3 $client = Mockery::mock(PaymentClient::class);
4 
5 return $client;
6}
7 
8it('may buy a book', function () {
9 $client = mockPayments();
10})

Mocking

Mockování určitých částí vaší aplikace může být v některých případech nevyhnutelné, například u eventů, nahrávání souborů nebo během integrování třetích stran. Více informací.

Ukázka mockování requestu:

1Http::fake([
2 'google.com/*' => Http::response('foo@gmail.com', 200)
3]);
4 
5$response = resolve(FetchGoogleUserEmailAction::class)->run();
6 
7expect($response)->toBe('foo@gmail.com');

Ukázka mockování třídy:

1use function Pest\Laravel\mock;
2 
3mock(Client::class)
4 // You may need to check the passed arguments
5 ->withArgs(fn ($givenOrder) => $givenOrder->is($order))
6 // Or check the response
7 ->andReturn(true)
8 ->shouldReceive('acceptOrder')
9 // You also can check how many times the class should be called
10 ->never()
11 ->once()
12 ->twice()
13 ->times(3)

Pro tip: V případě, že vytváříte mock pro integraci externího API, měli byste také zajistit, že vaše testy netrefují oficiální endpointy - v Laravelu můžete zabránit těmto přímým requestům pomocí metody Http::preventStrayRequests(). Po zavolání této metody vyhodí každý test bez odpovídajícího mocku výjimku. Více informací

Fixtures

Fixtures jsou statické soubory používané pro testování a měly by být umístěny v adresáři "fixtures". Mohou být použity v testech k simulaci skutečných zdrojů dat nebo k poskytnutí specifických podmínek pro testování.

Ukázky použití

1$payment = base_path('tests/fixtures/payment.xml');
2 
3app(ProcessPaymentAction::class)->run($payment, ...);

Pojmenování

Pro zajištění správného pojmenování vašich testů se doporučuje postupovat podle poskytnutého příkladu.

1// Good examples - lowercase, descriptive
2test('payment can be processed', function() {
3 ...
4});
5 
6it('has a welcome page', function() {
7 ...
8});
9 
10// Bad example - uppercase, low descriptive
11test('PAYMENT', function() {
12 ...
13});
14 
15it('sums', function() {
16 ...
17});
Edit this page

We are hiring!