Artikkelit

Opi tekemään testejä Laravelissa yksinkertaisilla esimerkeillä PHPUnitilla ja PESTillä

Mitä tulee automaattisiin testeihin tai yksikkötesteihin, millä tahansa ohjelmointikielellä on kaksi vastakkaista mielipidettä:

  • Ajanhukkaa
  • Et voi tehdä ilman sitä

Joten tällä artikkelilla yritämme vakuuttaa entisen, erityisesti osoittamalla, kuinka helppoa on aloittaa automaattinen testaus Laravelissa.

Puhutaan ensin "miksi" ja sitten katsotaan esimerkkejä miten.

Miksi tarvitsemme automaattista testausta

Automaattiset testit suorittavat osia koodista ja raportoivat mahdollisista virheistä. Se on yksinkertaisin tapa kuvata niitä. Kuvittele, että sovelluksessa otetaan käyttöön uusi ominaisuus, jonka jälkeen henkilökohtainen robottiassistentti menisi testaamaan uutta ominaisuutta manuaalisesti ja samalla testaamaan, eikö uusi koodi rikkonut mitään vanhoista ominaisuuksista.

Tämä on tärkein etu: kaikkien ominaisuuksien automaattinen uudelleentestaus. Tämä saattaa tuntua ylimääräiseltä työltä, mutta jos et käske "robottia" tekemään sitä, meidän pitäisi vaihtoehtoisesti tehdä se manuaalisesti, eikö niin? 

Tai uusia ominaisuuksia voitaisiin julkaista testaamatta niiden toimivuutta, toivoen, että käyttäjät ilmoittavat virheistä.

Automaattiset testit voivat tarjota meille useita etuja:

  • Säästä manuaalisen testauksen aikaa;
  • Niiden avulla voit säästää aikaa sekä uudessa toteutuksessa että yhdistetyissä funktioissa välttämällä regressiota;
  • Kerro tämä etu kaikilla uusilla ominaisuuksilla ja kaikilla jo toteutetuilla ominaisuuksilla;
  • Kolme edellistä kohtaa koskevat jokaista uutta versiota;
  • ...

Yritä kuvitella sovelluksesi vuoden tai kahden kuluttua, ja tiimissä on uusia kehittäjiä, jotka eivät tiedä aiempina vuosina kirjoitettua koodia tai edes testaamista. 

Ensimmäiset automaattiset testimme

Suorittaaksesi ensimmäisen automaattinen testaus Laravelissa, sinun ei tarvitse kirjoittaa mitään koodia. Kyllä, luit oikein. Kaikki on jo konfiguroitu ja valmisteltu esiasennuksessadefiLaravelin nite, mukaan lukien ensimmäinen perusesimerkki.

Voit yrittää asentaa Laravel-projektin ja suorittaa ensimmäiset testit välittömästi:

laravel new project
cd project
php artisan test

Tämän pitäisi olla tulos konsolissasi:

Jos katsomme esidefiLaravelin ilta /tests, meillä on kaksi tiedostoa:

testit/Feature/ExampleTest.php :

class ExampleTest extends TestCase
{
    public function test_the_application_returns_a_successful_response()
    {
        $response = $this->get('/');
 
        $response->assertStatus(200);
    }
}

Sinun ei tarvitse tietää syntaksia ymmärtääksesi mitä täällä tapahtuu: lataa kotisivu ja tarkista, onko tilakoodi HTTP è "200 OK".

Tunnetaan myös menetelmän nimellä test_the_application_returns_a_successful_response() tulee luettavaksi tekstiksi, kun tarkastelet testituloksia, yksinkertaisesti korvaamalla alleviivaussymboli välilyönnillä.

testit/Unit/ExampleTest.php :

class ExampleTest extends TestCase
{
    public function test_that_true_is_true()
    {
        $this->assertTrue(true);
    }
}

Vaikuttaa vähän turhalta, tarkistaa, onko tämä totta? 

Puhumme erityisesti yksikkötesteistä hieman myöhemmin. Toistaiseksi sinun on ymmärrettävä, mitä jokaisessa testissä yleensä tapahtuu.

  • Jokainen testitiedosto kansiossa /tests on PHP-luokka, joka laajentaa TestCasea PHPUnit
  • Jokaisessa luokassa voit luoda useita menetelmiä, yleensä yhden menetelmän tilanteen testattavaksi
  • Kussakin menetelmässä on kolme toimenpidettä: tilanteen valmistelu, sitten toiminta ja sitten tarkistetaan (vahvistetaan), onko tulos odotettu

Rakenteellisesti se on kaikki mitä sinun tarvitsee tietää. Kaikki muu riippuu tarkalleen, mitä asioita haluat testata.

Luodaksesi tyhjän testiluokan, suorita tämä komento:

php artisan make:test HomepageTest

Tiedosto luodaan tests/Feature/HomepageTest.php:

class HomepageTest extends TestCase
{
    // Replace this method with your own ones
    public function test_example()
    {
        $response = $this->get('/');
 
        $response->assertStatus(200);
    }
}

Katsotaan nyt, mitä tapahtuu, jos testikoodi epäonnistuu Laravelissa

Katsotaan nyt, mitä tapahtuu, jos testiväitteet eivät tuota odotettua tulosta.

Muutetaan esimerkkitestit tällaisiksi:

class ExampleTest extends TestCase
{
    public function test_the_application_returns_a_successful_response()
    {
        $response = $this->get('/non-existing-url');
 
        $response->assertStatus(200);
    }
}
 
 
class ExampleTest extends TestCase
{
    public function test_that_true_is_false()
    {
        $this->assertTrue(false);
    }
}

Ja nyt, jos suoritamme komennon php artisan test uudelleen:

 FAIL  Tests\Unit\ExampleTest
⨯ that true is true
 
 FAIL  Tests\Feature\ExampleTest
⨯ the application returns a successful response
 
---
 
• Tests\Unit\ExampleTest > that true is true
Failed asserting that false is true.
 
at tests/Unit/ExampleTest.php:16
   12▕      * @return void
   13▕      */
   14▕     public function test_that_true_is_true()
   15▕     {
➜  16▕         $this->assertTrue(false);
   17▕     }
   18▕ }
   19▕
 
• Tests\Feature\ExampleTest > the application returns a successful response
Expected response status code [200] but received 404.
Failed asserting that 200 is identical to 404.
 
at tests/Feature/ExampleTest.php:19
   15▕     public function test_the_application_returns_a_successful_response()
   16▕     {
   17▕         $response = $this->get('/non-existing-url');
   18▕
➜  19▕         $response->assertStatus(200);
   20▕     }
   21▕ }
   22▕
 
 
Tests:  2 failed
Time:   0.11s

On olemassa kaksi epäonnistunutta testiä, jotka on merkitty FAIL-merkinnällä. Alla on selitykset ja nuolet osoittavat tarkan epäonnistuneiden testien rivin. Virheet ilmoitetaan tällä tavalla.

Esimerkki: Rekisteröintilomakkeen koodin testaus Laravelissa

Oletetaan, että meillä on lomake ja meidän on testattava erilaisia ​​​​tapauksia: tarkistamme epäonnistuuko se virheellisillä tiedoilla, tarkistamme onnistuuko se oikealla syötteellä jne.

Virallinen aloituspaketti Kirjailija: Laravel Breeze sisältää i testata sen toimivuutta. Katsotaanpa muutamia esimerkkejä sieltä:

tests/Feature/RegistrationTest.php

use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class RegistrationTest extends TestCase
{
    use RefreshDatabase;
 
    public function test_registration_screen_can_be_rendered()
    {
        $response = $this->get('/register');
 
        $response->assertStatus(200);
    }
 
    public function test_new_users_can_register()
    {
        $response = $this->post('/register', [
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => 'password',
            'password_confirmation' => 'password',
        ]);
 
        $this->assertAuthenticated();
        $response->assertRedirect(RouteServiceProvider::HOME);
    }
}

Tässä meillä on kaksi testiä yhdellä luokalla, koska ne molemmat liittyvät ilmoittautumislomakkeeseen: toinen tarkistaa, onko lomake ladattu oikein ja toinen tarkistaa, toimiiko lähetys hyvin.

Tutustukaamme vielä kahteen menetelmään tuloksen varmentamiseksi, ja vielä kaksi väitettä: $this->assertAuthenticated()$response->assertRedirect(). Voit tarkistaa kaikki saatavilla olevat väitteet virallisesta dokumentaatiosta PHPUnit e Laravelin vastaus . Huomaa, että aiheesta löytyy joitain yleisiä väitteitä $this, kun taas toiset tarkistavat tietyn $responsereittikutsusta.

Toinen tärkeä asia on use RefreshDatabase;lause, jossa on viiva, lisätty luokan yläpuolelle. Se on tarpeen, kun testitoimenpiteet voivat vaikuttaa tietokantaan, kuten tässä esimerkissä, loki lisää uuden merkinnän tietokantaan userstietokantataulukko. Tätä varten sinun tulee luoda erillinen testitietokanta, joka päivitetään php artisan migrate:freshaina kun testit suoritetaan.

Sinulla on kaksi vaihtoehtoa: luoda fyysisesti erillinen tietokanta tai käyttää muistissa olevaa SQLite-tietokantaa. Molemmat on määritetty tiedostossa phpunit.xmltarjotaan oletuksenadefinita kanssa Laravel. Tarvitset erityisesti tämän osan:

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="BCRYPT_ROUNDS" value="4"/>
    <env name="CACHE_DRIVER" value="array"/>
    <!-- <env name="DB_CONNECTION" value="sqlite"/> -->
    <!-- <env name="DB_DATABASE" value=":memory:"/> -->
    <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>

Katso DB_CONNECTIONDB_DATABASEketä kommentoida? Jos sinulla on SQLite palvelimellasi, yksinkertaisin toimenpide on yksinkertaisesti poistaa nämä rivit kommenteista ja testisi suoritetaan muistissa olevaa tietokantaa vastaan.

Tässä testissä sanomme, että käyttäjä tunnistetaan onnistuneesti ja ohjataan oikealle kotisivulle, mutta voimme myös testata tietokannan todellisia tietoja.

Tämän koodin lisäksi:

$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);

Voimme myös käyttää tietokantatestin väitteet ja tee jotain näin:

$this->assertDatabaseCount('users', 1);
 
// Or...
$this->assertDatabaseHas('users', [
    'email' => 'test@example.com',
]);

Esimerkki kirjautumissivusta

Katsotaan nyt toinen esimerkki Laravel Breezen kirjautumissivusta

tests/Feature/AuthenticationTest.php:

class AuthenticationTest extends TestCase
{
    use RefreshDatabase;
 
    public function test_login_screen_can_be_rendered()
    {
        $response = $this->get('/login');
 
        $response->assertStatus(200);
    }
 
    public function test_users_can_authenticate_using_the_login_screen()
    {
        $user = User::factory()->create();
 
        $response = $this->post('/login', [
            'email' => $user->email,
            'password' => 'password',
        ]);
 
        $this->assertAuthenticated();
        $response->assertRedirect(RouteServiceProvider::HOME);
    }
 
    public function test_users_can_not_authenticate_with_invalid_password()
    {
        $user = User::factory()->create();
 
        $this->post('/login', [
            'email' => $user->email,
            'password' => 'wrong-password',
        ]);
 
        $this->assertGuest();
    }
}

Kyse on kirjautumislomakkeesta. Logiikka on samanlainen kuin rekisteröinti, eikö? Mutta kolme menetelmää kahden sijaan, joten tämä on esimerkki sekä hyvien että huonojen skenaarioiden testaamisesta. Joten yleinen logiikka on, että sinun tulee testata molemmat tapaukset: milloin asiat menevät hyvin ja milloin ne epäonnistuvat.

Innovaatio-uutiskirje
Älä missaa tärkeimpiä innovaatioita koskevia uutisia. Rekisteröidy saadaksesi ne sähköpostitse.

Lisäksi, mitä näet tässä testissä, on käyttö Tietokantatehtaita : Laravel luo väärennetyn käyttäjän ( jälleen päivitetyssä testitietokannassasi ) ja yrittää sitten kirjautua sisään oikeilla tai väärillä tunnuksilla.

Jälleen kerran Laravel luo tehdasesityksendefinita vääriä tietoja varten Usermalli, laatikon ulkopuolella.

database/factories/UserFactory.php:

class UserFactory extends Factory
{
    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),
        ];
    }
}

Katsos, kuinka monta asiaa Laravel itse valmistaa, joten olisiko meidän helppoa aloittaa testaus?

Jos siis toteutamme php artisan testLaravel Breezen asentamisen jälkeen meidän pitäisi nähdä jotain tällaista:

 PASS  Tests\Unit\ExampleTest
✓ that true is true
 
 PASS  Tests\Feature\Auth\AuthenticationTest
✓ login screen can be rendered
✓ users can authenticate using the login screen
✓ users can not authenticate with invalid password
 
 PASS  Tests\Feature\Auth\EmailVerificationTest
✓ email verification screen can be rendered
✓ email can be verified
✓ email is not verified with invalid hash
 
 PASS  Tests\Feature\Auth\PasswordConfirmationTest
✓ confirm password screen can be rendered
✓ password can be confirmed
✓ password is not confirmed with invalid password
 
 PASS  Tests\Feature\Auth\PasswordResetTest
✓ reset password link screen can be rendered
✓ reset password link can be requested
✓ reset password screen can be rendered
✓ password can be reset with valid token
 
 PASS  Tests\Feature\Auth\RegistrationTest
✓ registration screen can be rendered
✓ new users can register
 
 PASS  Tests\Feature\ExampleTest
✓ the application returns a successful response
 
Tests:  17 passed
Time:   0.61s

Toiminnalliset testit verrattuna yksikkötesteihin ja muihin

Olet nähnyt alikansiot tests/Feature e tests/Unit ?. 

Mitä eroa niillä on? 

Laravel/PHP-ekosysteemin ulkopuolella on maailmanlaajuisesti useita erilaisia ​​automatisoituja testauksia. Voit löytää termejä kuten:

  • Yksikkötestit
  • Ominaisuuden testaus
  • Integraatiotestit
  • Toiminnalliset testit
  • Päästä päähän -testaus
  • Hyväksyntätestit
  • Savutestit
  • jne.

Se kuulostaa monimutkaiselta, ja todelliset erot tämäntyyppisten testien välillä ovat joskus epäselviä. Siksi Laravel on yksinkertaistanut kaikki nämä hämmentävät termit ja ryhmitellyt ne kahteen osaan: yksikkö/ominaisuus.

Yksinkertaisesti sanottuna ominaisuustestit yrittävät suorittaa sovellustesi todelliset toiminnot: hanki URL-osoite, kutsu API, jäljittele tarkkaa toimintaa, kuten lomakkeen täyttämistä. Ominaisuustestit suorittavat yleensä samat tai samankaltaiset toiminnot kuin kuka tahansa projektin käyttäjä tekisi manuaalisesti tosielämässä.

Yksikkötesteillä on kaksi merkitystä. Yleensä saatat huomata, että mitä tahansa automaattista testiä kutsutaan "yksikkötestaukseksi" ja koko prosessia voidaan kutsua "yksikkötestaukseksi". Mutta toiminnallisuuden ja yksikön kontekstissa tässä prosessissa on kyse tietyn ei-julkisen koodiyksikön testaamisesta erikseen. Sinulla on esimerkiksi Laravel-luokka, jossa on menetelmä, joka laskee jotain, kuten tilauksen kokonaishinnan parametreineen. Siksi yksikkötesti ilmoittaisi, palautetaanko kyseisestä menetelmästä (koodiyksiköstä) oikeat tulokset eri parametrein.

Yksikkötestin luomiseksi sinun on lisättävä lippu:

php artisan make:test OrderPriceTest --unit

Luotu koodi on sama kuin yksikköä edeltävä testidefiLaravel järjestelmä:

class OrderPriceTest extends TestCase
{
    public function test_example()
    {
        $this->assertTrue(true);
    }
}

Kuten näet, sitä ei ole olemassa RefreshDatabase, ja tämä on yksi defiyleisimmät yksikkötestimääritykset: se ei kosketa tietokantaa, se toimii "mustana laatikona", eristettynä käynnissä olevasta sovelluksesta.

Yritetään jäljitellä aiemmin mainitsemaani esimerkkiä, kuvitellaan, että meillä on palveluluokka OrderPrice.

app/Services/OrderPriceService.php:

class OrderPriceService
{
    public function calculatePrice($productId, $quantity, $tax = 0.0)
    {
        // Some kind of calculation logic
    }
}

Sitten yksikkötesti voisi näyttää tältä:

class OrderPriceTest extends TestCase
{
    public function test_single_product_no_taxes()
    {
        $product = Product::factory()->create(); // generate a fake product
        $price = (new OrderPriceService())->calculatePrice($product->id, 1);
        $this->assertEquals(1, $price);
    }
 
    public function test_single_product_with_taxes()
    {
        $price = (new OrderPriceService())->calculatePrice($product->id, 1, 20);
        $this->assertEquals(1.2, $price);
    }
 
    // More cases with more parameters
}

Omakohtaisen kokemukseni mukaan Laravel-projekteista suurin osa testeistä on ominaisuustestejä, ei yksikkötestejä. Ensin sinun on testattava, toimiiko sovelluksesi, niin kuin oikeat ihmiset käyttäisivät sitä.

Seuraavaksi, jos sinulla on erityisiä laskelmia tai logiikkaa, voit definire yksikkönä, parametreilla voit luoda yksikkötestejä erityisesti sitä varten.

Joskus testien kirjoittaminen vaatii itse koodin muokkaamista ja sen uudelleenmuodostamista "testattavammaksi": yksiköiden erottaminen erityisluokiksi tai menetelmiksi.

Milloin/miten testit suoritetaan?

Mikä on tämän todellinen käyttö php artisan test, milloin se pitäisi ajaa?

On olemassa erilaisia ​​lähestymistapoja yrityksesi työnkulusta riippuen, mutta yleensä sinun on varmistettava, että kaikki testit ovat "vihreitä" (eli virheettömiä), ennen kuin siirrät lopulliset koodimuutokset arkistoon.

Sitten työskentelet paikallisesti tehtäväsi parissa, ja kun luulet, että olet valmis, suorita testejä varmistaaksesi, ettet ole rikkonut mitään. Muista, että koodisi voi aiheuttaa virheitä paitsi logiikassasi, myös vahingossa rikkoa jonkin muun käyttäytymisen jonkun toisen kauan sitten kirjoitetussa koodissa.

Jos otamme askeleen pidemmälle, se on mahdollista automatisoida monet asioita. Erilaisten CI/CD-työkalujen avulla voit määrittää suoritettavat testit aina, kun joku työntää muutoksia tiettyyn Git-haaraan tai ennen koodin yhdistämistä tuotantohaaraan. Yksinkertaisin työnkulku olisi käyttää Github Actionsia erillinen video joka sen todistaa.

Mitä kannattaa testata?

Siitä, kuinka laaja ns. ”testattavuuden” tulisi olla, ollaan eri mieltä: kokeile jokaisella sivulla jokaista mahdollista toimenpidettä ja tapausta tai rajoita työ tärkeimpiin osiin.

Itse asiassa tässä olen samaa mieltä ihmisten kanssa, jotka syyttävät automatisoitua testausta siitä, että se vie enemmän aikaa kuin tuottaa todellista hyötyä. Tämä voi tapahtua, jos kirjoitat testejä jokaisesta yksityiskohdasta. Projektisi saattaa kuitenkin vaatia sitä: pääkysymys on "mikä on mahdollisen virheen hinta".

Toisin sanoen sinun on priorisoitava testausyrityksesi esittämällä kysymys "Mitä tapahtuisi, jos tämä koodi epäonnistuu?" Jos maksujärjestelmässäsi on virheitä, se vaikuttaa suoraan liiketoimintaan. Joten jos roolisi/käyttöoikeutesi toiminnallisuus on rikki, tämä on valtava tietoturvaongelma.

Pidän siitä, miten Matt Stauffer sanoi sen konferenssissa: "Sinun on ensin testattava ne asiat, jotka epäonnistuessaan saisivat sinut irtisanoutumaan työstäsi." Tietysti se on liioittelua, mutta ymmärrät ajatuksen: kokeile ensin tärkeitä asioita. Ja sitten muita ominaisuuksia, jos sinulla on aikaa.

PEST: uusi vaihtoehto PHPUnitille

Kaikki yllä olevat esimerkit perustuvat Laravelin esitestaustyökaluundefiiltapäivä: PHPUnit . Mutta vuosien varrella ekosysteemiin on ilmestynyt muita työkaluja, ja yksi viimeisimmistä suosituista on PEST . Laravelin virallisen työntekijän luoma Nuno Maduro , pyrkii yksinkertaistamaan syntaksia, mikä tekee testien koodin kirjoittamisesta entistä nopeampaa.

Konepellin alla se kulkee su PHPUnit, lisäkerroksena, yrittää vain minimoida joitain ennalta toistettuja osiadefiPHPUnit-koodin loppu.

Katsotaanpa esimerkkiä. Muista ominaisuustestiä edeltävä luokkadefinited Laravelissa? Muistutan sinua:

namespace Tests\Feature;
 
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
    public function test_the_application_returns_a_successful_response()
    {
        $response = $this->get('/');
 
        $response->assertStatus(200);
    }
}

Tiedätkö miltä sama testi näyttäisi PESTin kanssa?

test('the application returns a successful response')->get('/')->assertStatus(200);

Kyllä, YKSI koodirivi ja siinä se. Joten PESTin tavoitteena on poistaa yleiskustannukset:

  • Luokkien ja menetelmien luominen kaikkeen;
  • Testitapauksen laajennus;
  • Asettamalla toiminnot eri riveille: PESTissä voit ketjuttaa ne yhteen.

Luodaksesi PEST-testin Laravelissa sinun on määritettävä ylimääräinen lippu:

php artisan make:test HomepageTest --pest

Tätä kirjoitettaessa PEST on varsin suosittu Laravel-kehittäjien keskuudessa, mutta on henkilökohtainen valintasi, käytätkö tätä lisätyökalua ja opitko sen syntaksin sekä PHPUnit-huomautuksen.

BlogInnovazione.it

Innovaatio-uutiskirje
Älä missaa tärkeimpiä innovaatioita koskevia uutisia. Rekisteröidy saadaksesi ne sähköpostitse.

Viimeaikaiset artikkelit

Veeam tarjoaa kattavimman tuen kiristysohjelmille suojauksesta vastaukseen ja palautukseen

Veeamin Coveware tarjoaa jatkossakin kyberkiristystapahtumien reagointipalveluita. Coveware tarjoaa rikosteknisiä ja korjaavia ominaisuuksia…

Huhtikuu 23 2024

Vihreä ja digitaalinen vallankumous: Kuinka ennakoiva huolto muuttaa öljy- ja kaasuteollisuutta

Ennakoiva huolto mullistaa öljy- ja kaasualan innovatiivisella ja ennakoivalla lähestymistavalla laitosten hallintaan.…

Huhtikuu 22 2024

Ison-Britannian kilpailuviranomainen herättää BigTech-hälytyksen GenAI:sta

Britannian CMA on antanut varoituksen Big Techin käyttäytymisestä tekoälymarkkinoilla. Siellä…

Huhtikuu 18 2024

Casa Green: energiavallankumous kestävän tulevaisuuden puolesta Italiassa

Euroopan unionin rakennusten energiatehokkuuden parantamiseksi laatima "Green Houses" -asetus on saanut lainsäädäntöprosessinsa päätökseen…

Huhtikuu 18 2024