Artikelen

Léiert wéi Tester zu Laravel mat einfache Beispiller maachen, mat PHPUnit a PEST

Wann et ëm automatiséiert Tester oder Eenheetstester kënnt, an all Programméierungssprooch, ginn et zwou opposéierend Meenungen:

  • verluer Zäit
  • Dir kënnt net ouni et maachen

Also, mat dësem Artikel wäerte mir probéieren déi fréier ze iwwerzeegen, besonnesch andeems Dir demonstréiert wéi einfach et ass fir mat automatiséiertem Testen zu Laravel unzefänken.

Als éischt schwätze mer iwwer de "Firwat", a kucke mer dann e puer Beispiller vu wéi.

Firwat brauche mir automatiséiert Tester

Automatiséiert Tester lafen Deeler vum Code a mellen all Feeler. Dat ass deen einfachste Wee fir se ze beschreiwen. Stellt Iech vir datt Dir eng nei Feature an enger App ausrollt, an da géif e perséinleche Roboter Assistent goen an déi nei Feature manuell testen, wärend och testen ob den neie Code keng vun den alen Features brécht.

Dëst ass den Haaptvirdeel: all Funktiounen automatesch nei testen. Dëst kéint wéi extra Aarbecht schéngen, awer wann Dir dem "Robot" net seet et ze maachen, sollte mir et alternativ manuell maachen, oder? 

Oder nei Features kënne verëffentlecht ginn ouni ze testen ob se funktionnéieren, an der Hoffnung datt d'Benotzer Bugs mellen.

Automatiséiert Tester kënnen eis verschidde Virdeeler ginn:

  • Spuert manuell Testzäit;
  • Si erlaben Iech Zäit ze spueren souwuel op déi nei implementéiert Funktioun an op de konsolidéierte Funktiounen andeems Dir Regressioun vermeit;
  • Multiplizéiert dëse Virdeel duerch all nei Fonctiounen an all Fonctiounen déi scho implementéiert sinn;
  • Déi dräi virdrun Punkte gëllen fir all nei Versioun;
  • ...

Probéiert Iech Är Applikatioun an engem Joer oder zwee virzestellen, mat neien Entwéckler am Team, déi de Code net kennen, deen an de Jore virdrun geschriwwe gouf, oder souguer wéi een et testen. 

Eis éischt automatiséiert Tester

Fir déi éischt Leeschtunge automatiséiert Testen zu Laravel, Dir braucht kee Code ze schreiwen. Jo, Dir liest dat richteg. Alles ass scho konfiguréiert a virbereet an der Pre-Installatioundefinite vun Laravel, dorënner déi éischt Basis Beispill.

Dir kënnt probéieren e Laravel Projet z'installéieren an déi éischt Tester direkt ausféieren:

laravel new project
cd project
php artisan test

Dëst sollt d'Resultat an Ärer Konsole sinn:

Wa mir e Bléck op d'PredefiNuecht vun Laravel /tests, hu mir zwee Dateien:

tests/Feature/ExampleTest.php :

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

Dir musst keng Syntax kennen fir ze verstoen wat hei lass ass: lued d'Homepage a kontrolléiert ob de Statuscode HTTP è "200 OK".

Och bekannt als Method Numm test_the_application_returns_a_successful_response() gëtt liesbaren Text wann Dir d'Testresultater kuckt, einfach andeems Dir d'Ënnerstreckungssymbol mat engem Raum ersetzt.

tests/Unit/ExampleTest.php :

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

Schéngt e bëssen Sënnlos, iwwerpréift fir ze kucken ob dëst richteg ass? 

Mir schwätze speziell iwwer Eenheetstester e bësse méi spéit. Fir de Moment musst Dir verstoen wat allgemeng an all Test geschitt.

  • All Testdatei am Dossier /tests ass eng PHP Klass déi den TestCase vun PHPUnit
  • Bannent all Klass kënnt Dir verschidde Methoden erstellen, normalerweis eng Method fir eng Situatioun ze testen
  • Bannent all Method ginn et dräi Aktiounen: d'Situatioun virbereeden, dann handelen an dann verifizéieren (bestätegen) ob d'Resultat wéi erwaart ass

Strukturell ass dat alles wat Dir wësse musst, alles anescht hänkt vun de genaue Saachen of, déi Dir wëllt testen.

Fir eng eidel Testklass ze generéieren, fuert einfach dëse Kommando aus:

php artisan make:test HomepageTest

De Fichier gëtt generéiert 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);
    }
}

Loosst eis elo kucken wat geschitt wann en Testcode am Laravel feelt

Loosst eis elo kucken wat geschitt wann d'Testbehaaptungen net dat erwaart Resultat zréckginn.

Loosst eis d'Beispill Tester op dëst änneren:

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

An elo, wa mir de Kommando lafen php artisan test wieder:

 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

Et ginn zwee gescheitert Tester, markéiert als FAIL, mat Erklärungen hei drënner a Pfeile weisen op déi exakt Linn vun Tester déi gescheitert sinn. Feeler ginn op dës Manéier uginn.

Beispill: Testen Aschreiwung Form Code zu Laravel

Ugeholl, mir hunn e Formulaire a mir musse verschidde Fäll testen: mir iwwerpréiwen ob et mat ongültege Donnéeën feelt, mir iwwerpréiwen ob et mat der korrekter Input geléngt, etc.

Den offiziellen Starter Kit vum Laravel Breeze enthält i d'Funktionalitéit dobannen testen. Loosst eis e puer Beispiller vun do kucken:

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

Hei hu mir zwee Tester an enger Klass, well se allebéid mam Umeldungsformular bezéien: Ee kontrolléiert ob de Formulaire richteg gelueden ass an eng aner kontrolléiert ob d'Soumissioun gutt funktionnéiert.

Loosst eis mat zwou méi Methoden vertraut ginn fir d'Resultat z'iwwerpréiwen, zwou weider Behaaptungen: $this->assertAuthenticated()$response->assertRedirect(). Dir kënnt all d'Behaaptungen, déi an der offizieller Dokumentatioun verfügbar sinn, iwwerpréiwen PHPUnit e Laravel Äntwert . Notéiert datt e puer allgemeng Behaaptungen zum Thema geschéien $this, während anerer kontrolléieren déi spezifesch $responsevun der Streck Opruff.

Eng aner wichteg Saach ass de use RefreshDatabase;Ausso, mam Schlag, iwwer d'Klass agebaut. Et ass néideg wann Testaktiounen d'Datebank beaflosse kënnen, wéi an dësem Beispill, de Logbicher bäidréit eng nei Entrée an der usersDatebank Dësch. Fir dëst, sollt Dir eng separat Test Datebank schafen déi mat aktualiséiert ginn php artisan migrate:freshall Kéier wann d'Tester lafen.

Dir hutt zwou Méiglechkeeten: kierperlech eng separat Datebank erstellen oder eng In-Memory SQLite Datebank benotzen. Béid sinn an der Datei konfiguréiert phpunit.xmlpar défaut zur Verfügung gestalltdefinit mat Laravel. Speziell braucht Dir dësen Deel:

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

Kuckt de DB_CONNECTIONDB_DATABASEop ween gin kommentéiert? Wann Dir SQLite op Ärem Server hutt, ass déi einfachst Handlung dës Zeilen einfach ze kommentéieren an Är Tester lafen géint dës In-Memory Datebank.

An dësem Test soen mir datt de Benotzer erfollegräich authentifizéiert an op déi richteg Homepage ëmgeleet gëtt, awer mir kënnen och déi aktuell Donnéeën an der Datebank testen.

Zousätzlech zu dësem Code:

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

Mir kënnen och benotzen d'Datebank Testbehaaptungen a maacht esou eppes:

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

Beispill vun der Login Säit

Loosst eis elo en anert Beispill vun enger Login Säit mat Laravel Breeze gesinn

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

Et geet ëm de Loginformular. D'Logik ass ähnlech wéi d'Registrierung, richteg? Awer dräi Methoden anstatt zwee, also ass dëst e Beispill fir gutt a schlecht Szenarie ze testen. Also, déi gemeinsam Logik ass datt Dir béid Fäll testen sollt: wann d'Saache gutt goen a wann se versoen.

Innovatioun Newsletter
Verpasst net déi wichtegst Neiegkeeten iwwer Innovatioun. Registréiert Iech fir se per E-Mail ze kréien.

Och wat Dir an dësem Test gesitt ass d'Benotzung vun Datebank Fabriken : Laravel erstellt gefälschte Benotzer ( erëm, op Är aktualiséiert Test Datebank ) a probéiert dann aloggen, mat korrekten oder falschen Umeldungsinformatiounen.

Nach eng Kéier, Laravel generéiert der Fabréck Predefinita mat falschen Donnéeën fir de UserModell, ausserhalb der Këscht.

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

Dir gesitt, wéi vill Saache si vum Laravel selwer virbereet, also wier et einfach fir eis ze testen?

Also wa mir ausféieren php artisan testnodeems Dir Laravel Breeze installéiert hutt, sollte mir sou eppes gesinn:

 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

Funktionell Tester am Verglach mat Eenheetstester an anerer

Dir hutt d'Ënnerfolder gesinn tests/Feature e tests/Unit ?. 

Wat ass den Ënnerscheed tëscht hinnen? 

Globalt, ausserhalb vum Laravel / PHP-Ökosystem, ginn et verschidden Aarte vun automatiséierten Tester. Dir kënnt Begrëffer fannen wéi:

  • Eenheet Tester
  • Feature Testen
  • Integratioun Tester
  • Funktionell Tester
  • Enn-zu-Enn Testen
  • Akzeptanz Tester
  • Rauchtesten
  • etc.

Et kléngt komplizéiert, an déi tatsächlech Differenzen tëscht dësen Aarte vun Tester sinn heiansdo verschwonn. Dofir huet Laravel all dës konfus Begrëffer vereinfacht an se an zwee gruppéiert: Eenheet / Feature.

Einfach gesot, Feature Tester probéieren déi tatsächlech Funktionalitéit vun Ären Uwendungen auszeféieren: kritt d'URL, rufft d'API un, miméiert dat exakt Verhalen wéi d'Form auszefëllen. Feature Tester maachen normalerweis déiselwecht oder ähnlech Operatiounen wéi all Projet Benotzer géif maachen, manuell, am richtege Liewen.

Eenheetstester hunn zwou Bedeitungen. Am Allgemengen kënnt Dir feststellen datt all automatiséiert Test "Eenheetstest" genannt gëtt an de ganze Prozess kann "Eenheetstest" genannt ginn. Awer am Kontext vu Funktionalitéit versus Eenheet geet dëse Prozess drëm fir eng spezifesch net-ëffentlech Code Eenheet ze testen, isoléiert. Zum Beispill hutt Dir eng Laravel Klass mat enger Method déi eppes berechent, wéi de Gesamtbestellungspräis mat Parameteren. Dofir géif den Eenheetstest soen ob korrekt Resultater vun där Method (Code-Eenheet) zréckginn, mat verschiddene Parameteren.

Fir en Eenheetstest ze generéieren, musst Dir e Fändel addéieren:

php artisan make:test OrderPriceTest --unit

De generéierte Code ass d'selwecht wéi de Pre-EenheetstestdefiLaravel System:

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

Wéi Dir gesitt, existéiert et net RefreshDatabase, an dëst ass ee vun defistäerkste gemeinsam Eenheet Test Definitiounen: et beréiert net der Datebank, et Wierker als "schwaarz Këscht", isoléiert vun der Lafen Applikatioun.

Probéieren dat Beispill ze imitéieren, dat ech virdru gesot hunn, loosst eis virstellen datt mir eng Serviceklass hunn OrderPrice.

app/Services/OrderPriceService.php:

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

Dann kéint den Eenheetstest sou eppes ausgesinn:

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
}

A menger perséinlecher Erfahrung mat Laravel Projete sinn déi grouss Majoritéit vun Tester Feature Tester, net Eenheetstester. Als éischt musst Dir testen ob Är Applikatioun funktionnéiert, sou wéi richteg Leit se benotze géifen.

Nächst, wann Dir speziell Berechnungen oder Logik hutt, kënnt Dir definire als Eenheet, mat Parameteren, Dir kënnt Eenheet Tester speziell fir déi schafen.

Heiansdo erfuerdert d'Schreiwe vun Tester de Code selwer z'änneren an ze refactoréieren fir et méi "testbar" ze maachen: d'Eenheeten a speziell Klassen oder Methoden ze trennen.

Wéini / wéi Tester ze maachen?

Wat ass den eigentleche Gebrauch vun dësem php artisan test, wéini soll Dir et lafen?

Et gi verschidde Approchen, ofhängeg vun Ärem Business Workflow, awer allgemeng musst Dir suergen datt all Tester "gréng" sinn (dh Feelerfräi) ier Dir déi lescht Code Ännerungen an de Repository dréckt.

Da schafft Dir lokal op Är Aufgab, a wann Dir mengt datt Dir fäerdeg sidd, lafen e puer Tester fir sécher ze stellen datt Dir näischt gebrach hutt. Denkt drun, Äre Code kann Bugs verursaachen net nëmmen an Ärer eegener Logik, awer och onbewosst en anert Verhalen an engem anere säi Code briechen, dee viru laanger Zäit geschriwwe gouf.

Wa mir et e Schrëtt méi wäit huelen, ass et méiglech ze automatiséieren molt Saachen. Mat verschiddenen CI / CD Tools kënnt Dir Tester spezifizéieren fir ze lafen wann iergendeen Ännerungen op eng spezifesch Git Branche dréckt oder ier Dir Code an d'Produktiounszweig fusionéiert. Deen einfachsten Workflow wier Github Actions ze benotzen, ech hunn eng separat Video wat et beweist.

Wat sollt Dir testen?

Et gi verschidde Meenungen iwwer wéi grouss de sougenannte "Testofdeckung" soll sinn: probéiert all méiglech Operatioun a Fall op all Säit, oder limitéiert d'Aarbecht op déi wichtegst Deeler.

Tatsächlech ass dëst wou ech mat Leit averstane sinn, déi den automatiséierten Test virgeworf hunn méi Zäit ze huelen wéi tatsächlech Benefice ze liwweren. Dëst ka geschéien wann Dir Tester fir all Detail schreift. Dat gesot, et kann vun Ärem Projet erfuerderlech sinn: d'Haaptfro ass "wat ass de Präis vum potenzielle Feeler".

An anere Wierder, Dir musst Är Testerefforten prioritär stellen andeems Dir d'Fro stellt "Wat géif geschéien wann dëse Code gescheitert?" Wann Äre Bezuelsystem Bugs huet, wäert et direkt d'Geschäft beaflossen. Also wann d'Funktionalitéit vun Äre Rollen / Permissiounen gebrach ass, ass dëst e risegt Sécherheetsprobleem.

Ech hu gär wéi de Matt Stauffer et op enger Konferenz gesat huet: "Dir musst éischt déi Saachen testen, déi, wa se versoen, Iech vun Ärer Aarbecht entlooss ginn." Natierlech ass dat iwwerdreiwen, awer Dir kritt d'Iddi: probéiert éischt déi wichteg Saachen. An dann aner Funktiounen, wann Dir Zäit hutt.

PEST: nei Alternativ zu PHPUnit

All déi uewe genannte Beispiller baséieren op Laravel Pre-Test-TooldefiNuecht: PHPUnit . Awer iwwer d'Jore sinn aner Tools am Ökosystem opgetaucht an ee vun de leschte populär ass PEST . Erstellt vum offiziellen Laravel Employé Nuno Maduro , zielt fir d'Syntax ze vereinfachen, sou datt de Code fir Tester nach méi séier schreift.

Ënnert der Hood leeft et su PHPUnit, als zousätzlech Schicht, probéiert just e puer pre-widderholl Deeler ze minimiséierendefinet vum PHPUnit Code.

Loosst eis e Beispill kucken. Erënneren der Pre-Funktioun Test Klassdefizu Laravel gelieft? Ech wäert Iech erënneren:

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

Wësst Dir wéi dee selwechten Test mat PEST ausgesäit?

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

Jo, ENG Zeil vum Code an dat ass et. Also, d'Zil vu PEST ass d'Overhead vun:

  • Schafen Klassen a Methoden fir alles;
  • Test Fall Extensioun;
  • Andeems Dir Aktiounen op getrennten Zeilen setzt: am PEST kënnt Dir se matenee ketten.

Fir e PEST Test zu Laravel ze generéieren, musst Dir en zousätzleche Fändel uginn:

php artisan make:test HomepageTest --pest

Wéi vun dësem Schreiwen ass PEST zimlech populär ënner Laravel Entwéckler, awer et ass Är perséinlech Präferenz ob Dir dëst zousätzlech Tool benotzt a seng Syntax léiert, souwéi eng PHPUnit Notiz.

BlogInnovazione.it

Innovatioun Newsletter
Verpasst net déi wichtegst Neiegkeeten iwwer Innovatioun. Registréiert Iech fir se per E-Mail ze kréien.

Recent Artikelen

D'Zukunft ass hei: Wéi d'Schëfferindustrie d'Weltwirtschaft revolutionéiert

De Marinesecteur ass eng richteg global wirtschaftlech Muecht, déi op e 150 Milliarde Maart navigéiert ass ...

1 Mee 2024

Verëffentlecher an OpenAI ënnerschreiwen Ofkommes fir de Flux vun Informatioun ze regléieren, déi vu Kënschtlech Intelligenz veraarbecht gëtt

De leschte Méindeg huet d'Financial Times en Deal mat OpenAI ugekënnegt. FT lizenzéiert säi Weltklass Journalismus ...

30 Abrëll 2024

Online Bezuelungen: Hei ass wéi Streaming Servicer Iech fir ëmmer bezuelen

Millioune vu Leit bezuelen fir Streaming Servicer, a bezuelen monatlecht Abonnementskäschte. Et ass allgemeng Meenung datt Dir ...

29 Abrëll 2024

Veeam huet déi ëmfaassendst Ënnerstëtzung fir Ransomware, vu Schutz bis Äntwert an Erhuelung

Coveware vu Veeam wäert weider Cyber ​​Erpressung Tëschefall Äntwert Servicer ubidden. Coveware wäert Forensik a Sanéierungsfäegkeeten ubidden ...

23 Abrëll 2024