Greinar

Lærðu hvernig á að gera próf í Laravel með einföldum dæmum, með PHPUnit og PEST

Þegar kemur að sjálfvirkum prófum eða einingaprófum, á hvaða forritunarmáli sem er, þá eru tvær andstæðar skoðanir:

  • Tímasóun
  • Þú getur ekki verið án þess

Svo með þessari grein munum við reyna að sannfæra þann fyrrnefnda, sérstaklega með því að sýna fram á hversu auðvelt það er að byrja með sjálfvirkar prófanir í Laravel.

Fyrst skulum við tala um „af hverju“ og síðan skulum við sjá nokkur dæmi um hvernig.

Af hverju við þurfum sjálfvirkar prófanir

Sjálfvirk próf keyra hluta kóðans og tilkynna allar villur. Það er einfaldasta leiðin til að lýsa þeim. Ímyndaðu þér að setja út nýjan eiginleika í appi, og síðan myndi persónulegur aðstoðarmaður vélmenna fara og prófa nýja eiginleikann handvirkt, á sama tíma og prófa hvort nýi kóðinn hafi ekki brotið neina af gömlu eiginleikum.

Þetta er helsti kosturinn: endurprófa alla eiginleika sjálfkrafa. Þetta gæti virst vera aukavinna, en ef þú segir „vélmenninu“ ekki að gera það, ættum við að öðrum kosti að gera það handvirkt, ekki satt? 

Eða hægt væri að gefa út nýja eiginleika án þess að prófa hvort þeir virki, í von um að notendur tilkynni um villur.

Sjálfvirk próf geta gefið okkur nokkra kosti:

  • Sparaðu handvirkan prófunartíma;
  • Þeir gera þér kleift að spara tíma bæði á nýju aðgerðinni sem er útfærð og á sameinuðu aðgerðunum með því að forðast afturför;
  • Margfaldaðu þennan ávinning með öllum nýjum eiginleikum og öllum eiginleikum sem þegar hafa verið innleiddir;
  • Fyrri þrír punktar eiga við um hverja nýja útgáfu;
  • ...

Reyndu að ímynda þér forritið þitt eftir eitt eða tvö ár, með nýjum forriturum í teyminu sem þekkja ekki kóðann sem skrifaður var á árum áður, eða jafnvel hvernig á að prófa hann. 

Fyrstu sjálfvirku prófin okkar

Til að framkvæma fyrsta sjálfvirkar prófanir í Laravel, þú þarft ekki að skrifa neinn kóða. Já, þú last það rétt. Allt er þegar stillt og undirbúið í foruppsetningunnidefikvöldið á Laravel, þar á meðal fyrsta grunndæmið.

Þú getur prófað að setja upp Laravel verkefni og keyrt fyrstu prófin strax:

laravel new project
cd project
php artisan test

Þetta ætti að vera niðurstaðan í stjórnborðinu þínu:

Ef við skoðum forsrhdefikvöld Laravel /tests, við höfum tvær skrár:

próf/Eiginleiki/ExampleTest.php:

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

Þú þarft ekki að kunna neina setningafræði til að skilja hvað er að gerast hér: hlaðið heimasíðunni og athugaðu hvort stöðukóði HTTP è "200 OK".

Einnig þekkt sem aðferðarheitið test_the_application_returns_a_successful_response() verður læsilegur texti þegar þú skoðar prófunarniðurstöðurnar, einfaldlega með því að skipta út undirstrikinu fyrir bil.

tests/Unit/ExampleTest.php :

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

Virðist svolítið tilgangslaust, að athuga hvort þetta sé satt? 

Við munum tala sérstaklega um einingarpróf aðeins síðar. Í bili þarftu að skilja hvað gerist almennt í hverju prófi.

  • Hver prófskrá í möppunni /tests er PHP flokkur sem framlengir TestCase af PHPUnit
  • Innan hvers flokks geturðu búið til margar aðferðir, venjulega eina aðferð til að prófa aðstæður
  • Innan hverrar aðferðar eru þrjár aðgerðir: að undirbúa ástandið, grípa síðan til aðgerða og síðan sannreyna (staðfesta) hvort niðurstaðan sé eins og búist var við

Byggingarlega séð er það allt sem þú þarft að vita, allt annað veltur á nákvæmlega hlutunum sem þú vilt prófa.

Til að búa til tóman prófunarflokk skaltu einfaldlega keyra þessa skipun:

php artisan make:test HomepageTest

Skráin er búin til 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);
    }
}

Nú skulum við sjá hvað gerist ef prófunarkóði mistekst í Laravel

Við skulum nú sjá hvað gerist ef prófstaðhæfingarnar skila ekki væntanlegum niðurstöðum.

Við skulum breyta dæmiprófunum í þetta:

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);
    }
}

Og nú, ef við keyrum skipunina php artisan test aftur:

 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

Það eru tvö fallin próf, merkt sem FAIL, með skýringum hér að neðan og örvum sem benda á nákvæma línu af prófum sem féllu. Villur eru sýndar með þessum hætti.

Dæmi: Prófunarkóða skráningareyðublaðs í Laravel

Segjum að við höfum eyðublað og við þurfum að prófa ýmis tilvik: við athugum hvort það mistekst með ógildum gögnum, við athugum hvort það heppnast með réttu inntakinu o.s.frv.

Opinbera byrjendasettið eftir Laravel Breeze felur í sér i að prófa virknina í því. Við skulum skoða nokkur dæmi þaðan:

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);
    }
}

Hér erum við með tvö próf í einum flokki, þar sem þau tengjast bæði skráningareyðublaðinu: annað athugar hvort eyðublaðið sé rétt hlaðið og annað athugar hvort innsendingin virki vel.

Við skulum kynnast tveimur aðferðum til viðbótar til að sannreyna niðurstöðuna, tvær fullyrðingar í viðbót: $this->assertAuthenticated()$response->assertRedirect(). Þú getur athugað allar fullyrðingar sem eru tiltækar í opinberum skjölum PHPUnit e Laravel svar . Athugið að nokkrar almennar fullyrðingar koma fram um efnið $this, á meðan aðrir athuga hið sérstaka $responsefrá leiðarkallinu.

Annað mikilvægt atriði er use RefreshDatabase;yfirlýsingu, með strikinu, sett inn fyrir ofan bekkinn. Það er nauðsynlegt þegar prófunaraðgerðir geta haft áhrif á gagnagrunninn, eins og í þessu dæmi, skráning bætir við nýrri færslu í usersgagnagrunnstafla. Fyrir þetta ættir þú að búa til sérstakan prófunargagnagrunn sem verður uppfærður með php artisan migrate:freshí hvert sinn sem prófin eru keyrð.

Þú hefur tvo möguleika: að búa til sérstakan gagnagrunn eða nota SQLite gagnagrunn í minni. Báðir eru stilltir í skránni phpunit.xmlveitt sjálfgefiðdefinita með Laravel. Sérstaklega þarftu þennan hluta:

<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>

Sjáðu DB_CONNECTIONDB_DATABASEvið hverja er kommentað? Ef þú ert með SQLite á netþjóninum þínum, þá er einfaldasta aðgerðin að einfaldlega afskrifa þessar línur og prófin þín munu keyra á þann gagnagrunn í minni.

Í þessu prófi segjum við að notandinn sé auðkenndur og vísað á rétta heimasíðu, en við getum líka prófað raunveruleg gögn í gagnagrunninum.

Til viðbótar við þennan kóða:

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

Við getum líka notað fullyrðingar gagnagrunnsprófsins og gerðu eitthvað á þessa leið:

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

Dæmi um innskráningarsíðuna

Við skulum nú sjá annað dæmi um innskráningarsíðu með Laravel Breeze

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();
    }
}

Þetta snýst um innskráningarformið. Rökfræðin er svipuð skráningu, ekki satt? En þrjár aðferðir í stað tveggja, þannig að þetta er dæmi um að prófa bæði góðar og slæmar aðstæður. Svo, sameiginleg rökfræði er sú að þú ættir að prófa bæði tilvikin: þegar hlutirnir ganga vel og þegar þeir mistakast.

Nýsköpunarfréttabréf
Ekki missa af mikilvægustu fréttunum um nýsköpun. Skráðu þig til að fá þau með tölvupósti.

Einnig, það sem þú sérð í þessu prófi er notkun á Gagnagrunnsverksmiðjur : Laravel býr til falsa notanda ( aftur, á uppfærða prófunargagnagrunninum þínum ) og reynir síðan að skrá sig inn með réttum eða röngum skilríkjum.

Aftur býr Laravel til verksmiðjunnar fyrirdefinita með fölskum gögnum fyrir Userfyrirmynd, utan kassans.

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),
        ];
    }
}

Þú sérð, hversu margir hlutir eru útbúnir af Laravel sjálfu, svo væri auðvelt fyrir okkur að byrja að prófa?

Svo ef við framkvæmum php artisan testeftir að Laravel Breeze hefur verið sett upp ættum við að sjá eitthvað á þessa leið:

 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

Virknipróf borin saman við einingapróf og önnur

Þú hefur séð undirmöppurnar tests/Feature e tests/Unit ?. 

Hver er munurinn á þeim? 

Á heimsvísu, utan Laravel/PHP vistkerfisins, eru nokkrar gerðir af sjálfvirkum prófunum. Þú getur fundið hugtök eins og:

  • Einingapróf
  • Eiginleikaprófun
  • Samþættingarpróf
  • Virknipróf
  • Próf frá enda til enda
  • Viðtökupróf
  • Reykpróf
  • o.s.frv.

Það hljómar flókið og raunverulegur munur á þessum tegundum prófa er stundum óskýr. Þess vegna hefur Laravel einfaldað öll þessi ruglingslegu hugtök og flokkað þau í tvennt: einingu/eiginleika.

Einfaldlega sagt, eiginleikapróf reyna að framkvæma raunverulega virkni forritanna þinna: fáðu slóðina, hringdu í API, líktu eftir nákvæmri hegðun eins og að fylla út eyðublaðið. Eiginleikapróf framkvæma venjulega sömu eða svipaðar aðgerðir og allir verkefnanotendur myndu gera, handvirkt, í raunveruleikanum.

Einingapróf hafa tvær merkingar. Almennt séð gætirðu komist að því að öll sjálfvirk próf eru kölluð „einingaprófun“ og allt ferlið má kalla „einingaprófun“. En í samhengi við virkni á móti einingu snýst þetta ferli um að prófa ákveðna óopinbera kóðaeiningu, í einangrun. Til dæmis ertu með Laravel flokk með aðferð sem reiknar eitthvað, eins og heildarpöntunarverð með breytum. Þess vegna myndi einingaprófið gefa til kynna hvort réttar niðurstöður séu skilaðar frá þeirri aðferð (kóðaeining), með mismunandi breytum.

Til að búa til einingapróf þarftu að bæta við fána:

php artisan make:test OrderPriceTest --unit

Kóðinn sem myndaður er er sá sami og foreiningaprófiðdefiLaravel kerfi:

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

Eins og þú sérð er það ekki til RefreshDatabase, og þetta er ein af defiAlgengustu skilgreiningar á einingaprófum: hann snertir ekki gagnagrunninn, hann virkar sem „svartur kassi“, einangraður frá forritinu sem er í gangi.

Reynum að líkja eftir dæminu sem ég nefndi áðan, við skulum ímynda okkur að við séum með þjónustuflokk OrderPrice.

app/Services/OrderPriceService.php:

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

Þá gæti einingaprófið litið svona út:

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
}

Í persónulegri reynslu minni af Laravel verkefnum eru langflest próf eiginleikapróf, ekki einingapróf. Fyrst þarftu að prófa hvort forritið þitt virkar, eins og raunverulegt fólk myndi nota það.

Næst, ef þú ert með sérstaka útreikninga eða rökfræði geturðu það definire sem eining, með breytum, þú getur búið til einingapróf sérstaklega fyrir það.

Stundum krefst ritun prófa að breyta kóðanum sjálfum og breyta honum til að gera hann „prófanlegri“: aðgreina einingarnar í sérstaka flokka eða aðferðir.

Hvenær/hvernig á að framkvæma prófin?

Hver er raunveruleg notkun á þessu php artisan test, hvenær ættir þú að keyra það?

Það eru mismunandi aðferðir, allt eftir vinnuflæði fyrirtækisins, en almennt þarftu að tryggja að öll próf séu „græn“ (þ.e. villulaus) áður en þú ýtir síðustu kóðabreytingunum á geymsluna.

Síðan vinnur þú að verkefninu þínu á staðnum og þegar þú heldur að þú sért búinn skaltu keyra nokkrar prófanir til að ganga úr skugga um að þú hafir ekki brotið neitt. Mundu að kóðinn þinn getur valdið villum ekki aðeins í rökfræði þinni heldur einnig óviljandi brotið aðra hegðun í kóða einhvers annars sem skrifaður var fyrir löngu síðan.

Ef við tökum þetta skref lengra er hægt að gera sjálfvirkan margir hlutir. Með ýmsum CI/CD verkfærum geturðu tilgreint próf til að keyra hvenær sem einhver ýtir á breytingar á tiltekinni Git grein eða áður en kóða er sameinað í framleiðslugreininni. Einfaldasta vinnuflæðið væri að nota Github Actions, ég hef sér myndband sem sannar það.

Hvað ættir þú að prófa?

Það eru skiptar skoðanir um hversu stór svokölluð „prófunarumfjöllun“ ætti að vera: reyndu allar mögulegar aðgerðir og mál á hverri síðu, eða takmarkaðu vinnuna við mikilvægustu hlutana.

Reyndar er þetta þar sem ég er sammála fólki sem sakar sjálfvirkar prófanir um að taka lengri tíma en að veita raunverulegan ávinning. Þetta getur gerst ef þú skrifar próf fyrir hvert einasta smáatriði. Sem sagt, það gæti verið krafist af verkefninu þínu: aðalspurningin er „hvert er verðið á hugsanlegum villum“.

Með öðrum orðum, þú þarft að forgangsraða prófunarviðleitni þinni með því að spyrja spurningarinnar „Hvað myndi gerast ef þessi kóði mistókst? Ef greiðslukerfið þitt hefur galla mun það hafa bein áhrif á fyrirtækið. Þannig að ef virkni hlutverka/heimilda þinna er biluð er þetta mikið öryggisvandamál.

Mér líkar hvernig Matt Stauffer orðaði það á ráðstefnu: „Þú verður fyrst að prófa þá hluti sem, ef þeir mistakast, myndu reka þig úr starfi þínu. Auðvitað er það ofmælt, en þú færð hugmyndina: prófaðu fyrst mikilvægu hlutina. Og svo aðra eiginleika, ef þú hefur tíma.

PEST: nýr valkostur við PHPUnit

Öll ofangreind dæmi eru byggð á Laravel forprófunartækidefikvöld: PHPUnit . En í gegnum árin hafa önnur verkfæri birst í vistkerfinu og eitt af þeim nýjustu vinsælustu er PESTI . Búið til af opinberum starfsmanni Laravel Nuno Maduro , miðar að því að einfalda setningafræðina og gera ritun kóða fyrir próf enn hraðari.

Undir húddinu keyrir hann su PHPUnit, sem viðbótarlag, er bara að reyna að lágmarka nokkra fyrirfram endurtekna hlutadefiníð PHPUnit kóðans.

Við skulum líta á dæmi. Mundu forprófunartímanndefinötuð í Laravel? Ég mun minna þig á:

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);
    }
}

Veistu hvernig sama próf myndi líta út með PEST?

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

Já, EIN lína af kóða og það er það. Svo, markmið PEST er að fjarlægja kostnaður af:

  • Að búa til flokka og aðferðir fyrir allt;
  • Framlenging prófunartilviks;
  • Með því að setja aðgerðir á aðskildar línur: í PEST geturðu hlekkjað þær saman.

Til að búa til PEST próf í Laravel þarftu að tilgreina auka fána:

php artisan make:test HomepageTest --pest

Þegar þetta er skrifað er PEST nokkuð vinsælt meðal Laravel forritara, en það er persónulegt val þitt hvort þú notir þetta viðbótartól og lærir setningafræði þess, sem og PHPUnit athugasemd.

BlogInnovazione.it

Nýsköpunarfréttabréf
Ekki missa af mikilvægustu fréttunum um nýsköpun. Skráðu þig til að fá þau með tölvupósti.

Nýlegar greinar

Útgefendur og OpenAI skrifa undir samninga um að stjórna flæði upplýsinga sem unnið er með gervigreind

Síðasta mánudag tilkynnti Financial Times um samning við OpenAI. FT leyfir heimsklassa blaðamennsku…

30 Apríl 2024

Greiðslur á netinu: Hér er hvernig streymisþjónusta gerir þér kleift að borga að eilífu

Milljónir manna borga fyrir streymisþjónustu og greiða mánaðarlega áskriftargjöld. Það er almenn skoðun að þú…

29 Apríl 2024

Veeam býður upp á umfangsmesta stuðninginn fyrir lausnarhugbúnað, allt frá vernd til viðbragða og bata

Coveware frá Veeam mun halda áfram að veita viðbragðsþjónustu fyrir tölvukúgun. Coveware mun bjóða upp á réttar- og úrbótamöguleika ...

23 Apríl 2024

Græn og stafræn bylting: Hvernig forspárviðhald er að umbreyta olíu- og gasiðnaðinum

Forspárviðhald er að gjörbylta olíu- og gasgeiranum, með nýstárlegri og fyrirbyggjandi nálgun við verksmiðjustjórnun.…

22 Apríl 2024