Atik

Aprann kijan pou fè tès nan Laravel ak egzanp senp, lè l sèvi avèk PHPUnit ak PEST

Lè li rive tès otomatik oswa tès inite, nan nenpòt langaj pwogramasyon, gen de opinyon opoze:

  • Pèdi tan
  • Ou pa ka fè san li

Se konsa, ak atik sa a nou pral eseye konvenk ansyen an, espesyalman lè nou montre kouman li fasil pou kòmanse ak tès otomatik nan Laravel.

Premyèman, ann pale sou "poukisa", epi ann wè kèk egzanp sou fason.

Poukisa nou bezwen tès otomatik

Tès otomatik yo kouri pati nan kòd la epi rapòte nenpòt erè. Sa se fason ki pi senp pou dekri yo. Imajine woule yon nouvo karakteristik nan yon app, ak Lè sa a, yon asistan robo pèsonèl ta ale ak manyèlman teste nouvo karakteristik nan, pandan y ap tou teste si nouvo kòd la pa t kraze okenn nan ansyen karakteristik yo.

Sa a se avantaj prensipal la: repete tout karakteristik otomatikman. Sa a ta ka sanble travay siplemantè, men si ou pa di "robo" a fè li, nou ta dwe altènativman fè li manyèlman, dwa? 

Oswa nouvo karakteristik yo ta ka lage san yo pa teste si yo travay, avèk lespwa ke itilizatè yo pral rapòte pinèz.

Tès otomatik yo ka ban nou plizyè avantaj:

  • Sove tan tès manyèl;
  • Yo pèmèt ou ekonomize tan tou de sou nouvo fonksyon an aplike ak sou fonksyon yo konsolide pa evite regresyon;
  • Miltipliye benefis sa a pa tout nouvo karakteristik ak tout karakteristik deja aplike;
  • Twa pwen anvan yo aplike nan chak nouvo vèsyon;
  • ...

Eseye imajine aplikasyon w lan nan yon ane oswa de, ak nouvo devlopè nan ekip la ki pa konnen kòd ki te ekri nan ane anvan yo, oswa menm ki jan yo teste li. 

Premye tès otomatik nou yo

Pou fè premye a tès otomatik nan Laravel, ou pa bezwen ekri okenn kòd. Wi, ou li sa byen. Tout se deja configuré ak prepare nan pre-enstalasyon andefinite nan Laravel, ki gen ladan premye egzanp debaz la.

Ou ka eseye enstale yon pwojè Laravel epi kouri premye tès yo imedyatman:

laravel new project
cd project
php artisan test

Sa a ta dwe rezilta a nan konsole ou a:

Si nou gade nan pre adefinite nan Laravel /tests, nou gen de dosye:

tès/Feature/ExampleTest.php:

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

Ou pa bezwen konnen okenn sentaks pou w konprann sa k ap pase isit la: chaje paj kay la epi tcheke si kòd estati a. HTTP è "200 OK".

Konnen tou kòm non metòd la test_the_application_returns_a_successful_response() vin tèks lizib lè ou wè rezilta tès yo, tou senpleman pa ranplase senbòl souliye a ak yon espas.

tès/Inite/ExampleTest.php:

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

Li sanble yon ti jan initil, tcheke pou wè si sa a se vre? 

Nou pral pale espesyalman sou tès inite yon ti kras pita. Pou kounye a, ou bezwen konprann sa ki jeneralman k ap pase nan chak tès.

  • Chak dosye tès nan katab la /tests se yon klas PHP ki pwolonje TestCase nan PHPUnit
  • Nan chak klas, ou ka kreye plizyè metòd, anjeneral yon metòd pou yon sitiyasyon teste
  • Nan chak metòd gen twa aksyon: preparasyon sitiyasyon an, answit aksyon epi verifye (afime) si rezilta a se jan yo espere.

Estriktirèl, se tout sa ou bezwen konnen, tout lòt bagay depann sou bagay egzak ou vle teste.

Pou jenere yon klas tès vid, tou senpleman kouri lòd sa a:

php artisan make:test HomepageTest

Fichye a te pwodwi 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);
    }
}

Koulye a, ann wè sa k ap pase si yon kòd tès echwe nan Laravel

Ann gade kounye a sa k ap pase si afimasyon tès yo pa retounen rezilta espere a.

Ann chanje egzanp tès yo nan sa a:

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

Epi, koulye a, si nou kouri lòd la php artisan test ankò:

 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

Gen de tès ki echwe, ki make kòm FAIL, ak eksplikasyon anba a ak flèch ki montre liy egzak tès ki echwe. Erè yo endike fason sa a.

Egzanp: Tès kòd fòm enskripsyon nan Laravel

Sipoze nou gen yon fòm epi nou bezwen teste plizyè ka: nou tcheke si li echwe ak done envalid, nou tcheke si li reyisi ak opinyon ki kòrèk la, elatriye.

Twous demaraj ofisyèl la pa Laravel Breeze gen ladann mwen teste fonksyonalite ki nan li. Ann gade kèk egzanp soti nan la:

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

Isit la nou gen de tès nan yon klas, paske yo tou de gen rapò ak fòm enskripsyon an: youn tcheke si fòm nan chaje kòrèkteman ak yon lòt tcheke si soumèt la mache byen.

Se pou nou vin abitye ak de lòt metòd pou verifye rezilta a, de plis afimasyon: $this->assertAuthenticated()$response->assertRedirect(). Ou ka tcheke tout afimasyon ki disponib nan dokiman ofisyèl yo nan PHPUnit e Laravel Repons . Remake byen ke kèk afimasyon jeneral rive sou sijè a $this, pandan ke lòt moun tcheke espesifik la $responsesoti nan apèl la wout.

Yon lòt bagay enpòtan se la use RefreshDatabase;deklarasyon, ak konjesyon serebral la, antre anlè klas la. Li nesesè lè aksyon tès yo ka afekte baz done a, tankou nan egzanp sa a, antre ajoute yon nouvo antre nan userstab baz done. Pou sa, ou ta dwe kreye yon baz done tès separe ki pral mete ajou ak php artisan migrate:freshchak fwa tès yo ap kouri.

Ou gen de opsyon: fizikman kreye yon baz done separe oswa itilize yon baz done SQLite nan memwa. Tou de yo configuré nan dosye a phpunit.xmlbay pa defaultdefinita ak Laravel. Espesyalman, ou bezwen pati sa a:

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

Gade la DB_CONNECTIONDB_DATABASEkiyès yo fè kòmantè? Si ou gen SQLite sou sèvè ou a, aksyon ki pi senp la se tou senpleman dekomantè liy sa yo epi tès ou yo pral kouri kont baz done ki nan memwa sa a.

Nan tès sa a nou di ke itilizatè a avèk siksè otantifye ak redireksyon sou paj dakèy ki kòrèk la, men nou kapab tou teste done aktyèl la nan baz done a.

Anplis kòd sa a:

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

Nou ka itilize tou afimasyon tès baz done yo epi fè yon bagay tankou sa a:

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

Egzanp paj Login la

Ann gade kounye a yon lòt egzanp yon paj Login ak 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();
    }
}

Li se sou fòm nan login. Lojik la sanble ak enskripsyon an, pa vre? Men, twa metòd olye de de, kidonk sa a se yon egzanp tès tou de bon ak move senaryo. Se konsa, lojik komen an se ke ou ta dwe teste tou de ka yo: lè bagay yo ale byen ak lè yo echwe.

Bilten inovasyon
Pa rate nouvèl ki pi enpòtan sou inovasyon. Enskri pou resevwa yo pa imel.

Epitou, sa ou wè nan tès sa a se itilizasyon an Faktori baz done : Laravel kreye fo itilizatè ( ankò, sou baz done tès ou mete ajou ) ak Lè sa a, eseye konekte, ak kalifikasyon kòrèk oswa kòrèk.

Yon fwa ankò, Laravel jenere faktori a predefinita ak fo done pou la Usermodèl, deyò bwat la.

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

Ou wè, konbyen bagay yo prepare pa Laravel li menm, kidonk li ta fasil pou nou kòmanse teste?

Se konsa, si nou egzekite php artisan testapre enstale Laravel Breeze, nou ta dwe wè yon bagay tankou sa a:

 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

Tès fonksyonèl konpare ak tès inite yo ak lòt moun

Ou te wè sousdosye yo tests/Feature e tests/Unit ?. 

Ki diferans ki genyen ant yo? 

Globalman, andeyò ekosistèm Laravel/PHP, gen plizyè kalite tès otomatik. Ou ka jwenn tèm tankou:

  • Tès inite yo
  • Tès karakteristik
  • Tès entegrasyon
  • Tès fonksyonèl
  • Tès fen-a-fen
  • Tès akseptasyon
  • Tès lafimen
  • elatriye.

Li son konplike, ak diferans aktyèl ant kalite tès sa yo pafwa twoub. Se poutèt sa Laravel te senplifye tout tèm konfizyon sa yo epi gwoupe yo an de: inite/karakteristik.

Senpleman mete, tès karakteristik eseye egzekite fonksyonalite aktyèl la nan aplikasyon ou yo: jwenn URL la, rele API a, imite konpòtman an egzak tankou ranpli fòm nan. Tès karakteristik anjeneral fè operasyon yo menm oswa menm jan ak nenpòt itilizatè pwojè ta fè, manyèlman, nan lavi reyèl.

Tès inite yo gen de siyifikasyon. An jeneral, ou ka jwenn ke nenpòt tès otomatik yo rele "inite tès" ak tout pwosesis la ka rele "tès inite". Men, nan yon kontèks fonksyonalite kont inite, pwosesis sa a se sou tès yon inite espesifik ki pa piblik nan kòd, nan izolasyon. Pou egzanp, ou gen yon klas Laravel ak yon metòd ki kalkile yon bagay, tankou pri total lòd ak paramèt. Se poutèt sa, tès inite a ta endike si rezilta kòrèk yo retounen nan metòd sa a (inite kòd), ak paramèt diferan.

Pou jenere yon tès inite, ou bezwen ajoute yon drapo:

php artisan make:test OrderPriceTest --unit

Kòd pwodwi a se menm jan ak tès inite anvan andefiSistèm Laravel:

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

Kòm ou ka wè, li pa egziste RefreshDatabase, e sa a se youn nan defidefinisyon ki pi komen tès inite yo: li pa manyen baz done a, li travay kòm yon "bwat nwa", izole nan aplikasyon an kouri.

Eseye imite egzanp mwen mansyone pi bonè a, ann imajine nou gen yon klas sèvis OrderPrice.

app/Services/OrderPriceService.php:

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

Lè sa a, tès inite a ta ka sanble yon bagay tankou sa a:

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
}

Nan eksperyans pèsonèl mwen ak pwojè Laravel, vas majorite tès yo se Tès Karakteristik, pa Tès Inite. Premyèman, ou bezwen teste si aplikasyon w lan ap travay, fason moun reyèl ta itilize li.

Apre sa, si ou gen kalkil espesyal oswa lojik ou kapab defimwen kòm yon inite, ak paramèt, ou ka kreye tès inite espesyalman pou sa.

Pafwa, ekri tès yo mande pou modifye kòd la tèt li ak refactoring li pou fè li pi "testable": separe inite yo nan klas espesyal oswa metòd.

Kilè/kijan pou fè tès yo?

Ki itilizasyon aktyèl la nan sa a php artisan test, kilè ou ta dwe kouri li?

Gen diferan apwòch, tou depann de workflow biznis ou, men jeneralman ou bezwen asire ke tout tès yo "vèt" (sa vle di san erè) anvan pouse chanjman kòd final yo nan repozitwa a.

Lè sa a, ou travay lokalman sou travay ou, epi lè ou panse ou fini, kouri kèk tès asire w ke ou pa te kraze anyen. Sonje byen, kòd ou a ka lakòz ensèk non sèlman nan lojik ou a, men tou san entansyonèlman kraze kèk lòt konpòtman nan kòd yon lòt moun ekri depi lontan.

Si nou pran li yon etap pi lwen, li posib otomatize anpil bagay yo. Avèk divès kalite zouti CI/CD, ou ka presize tès yo kouri chak fwa yon moun pouse chanjman nan yon branch Git espesifik oswa anvan fusion kòd nan branch pwodiksyon an. Workflow ki pi senp la ta dwe sèvi ak Github Actions, mwen genyen yon videyo separe ki pwouve li.

Kisa ou ta dwe teste?

Gen opinyon diferan sou ki jan gwo sa yo rele "kouvèti tès la" ta dwe: eseye tout operasyon posib ak ka sou chak paj, oswa limite travay la nan pati ki pi enpòtan yo.

An reyalite, sa a se kote mwen dakò ak moun ki akize tès otomatik yo pran plis tan pase bay benefis aktyèl la. Sa ka rive si ou ekri tès pou chak ti detay. Sa te di, li ka mande pa pwojè ou a: kesyon prensipal la se "ki sa ki pri a nan erè potansyèl".

Nan lòt mo, ou bezwen priyorite efò tès ou yo lè w poze kesyon an "Kisa ki ta rive si kòd sa a echwe?" Si sistèm peman ou a gen ensèk, li pral dirèkteman afekte biznis la. Se konsa, si fonksyonalite wòl/pèmisyon ou yo kase, sa a se yon gwo pwoblèm sekirite.

Mwen renmen jan Matt Stauffer te di li nan yon konferans: "Ou dwe premye teste bagay sa yo ki, si yo echwe, ta fè ou revoke nan travay ou." Natirèlman sa a se yon egzajerasyon, men ou jwenn lide a: eseye bagay ki enpòtan an premye. Lè sa a, lòt karakteristik, si ou gen tan.

PEST: nouvo altènatif pou PHPUnit

Tout egzanp ki anwo yo baze sou zouti pre tès Laraveldefinwit: PHPUnit . Men, pandan ane yo, lòt zouti te parèt nan ekosistèm nan ak youn nan dènye yo popilè se PÈS . Kreye pa anplwaye ofisyèl Laravel Nuno Maduro , vize senplifye sentaks la, fè ekri kòd pou tès yo menm pi vit.

Anba kapo a, li kouri su PHPUnit, kòm yon kouch adisyonèl, jis ap eseye minimize kèk pati pre-repetedefifini nan kòd PHPUnit la.

Ann gade yon egzanp. Sonje klas tès pre karakteristik yodefinite nan Laravel? Mwen pral raple ou:

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

èske w konnen ki jan menm tès la ta sanble ak PEST?

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

Wi, YON liy kòd ak sa a. Se konsa, objektif PEST la se retire anlè a nan:

  • Kreye klas ak metòd pou tout bagay;
  • ekstansyon ka tès la;
  • Lè w mete aksyon sou liy separe: nan PEST ou ka chenn yo ansanm.

Pou jenere yon tès PEST nan Laravel, ou bezwen presize yon drapo adisyonèl:

php artisan make:test HomepageTest --pest

Kòm nan ekri sa a, PEST se byen popilè nan mitan devlopè Laravel, men li se preferans pèsonèl ou si w ap itilize zouti adisyonèl sa a epi aprann sentaks li yo, osi byen ke yon nòt PHPUnit.

BlogInnovazione.it

Bilten inovasyon
Pa rate nouvèl ki pi enpòtan sou inovasyon. Enskri pou resevwa yo pa imel.

Recent Articles

Nouvo entèlijans atifisyèl Google la ka modèl ADN, RNA ak "tout molekil lavi"

Google DeepMind ap prezante yon vèsyon amelyore nan modèl entèlijans atifisyèl li yo. Nouvo modèl amelyore bay non sèlman...

9 Me 2024

Eksplore Achitekti modilè Laravel la

Laravel, pi popilè pou sentaks elegant li yo ak karakteristik pwisan, tou bay yon fondasyon solid pou achitekti modilè. La…

9 Me 2024

Cisco Hypershield ak akizisyon de Splunk Nouvo epòk sekirite a kòmanse

Cisco ak Splunk ap ede kliyan akselere vwayaj yo nan Sant Operasyon Sekirite (SOC) nan tan kap vini an ak...

8 Me 2024

Pi lwen pase bò ekonomik la: pri ki pa evidan nan ransomware

Ransomware te domine nouvèl la pou de dènye ane yo. Pifò moun konnen byen ke atak...

6 Me 2024

Entèvansyon inovatè nan Reyalite Ogmante, ak yon espektatè Apple nan Poliklinik Catania

Yon operasyon oftalmoplasti lè l sèvi avèk Apple Vision Pro komèsyal viewer te fèt nan Poliklinik Catania ...

3 Me 2024

Benefis ki genyen nan paj koloran pou timoun - yon mond majik pou tout laj

Devlope ladrès motè amann atravè koloran prepare timoun yo pou ladrès ki pi konplèks tankou ekri. Pou koulè...

2 Me 2024

Lavni an se isit la: Ki jan endistri transpò a ap revolusyone ekonomi global la

Sektè naval la se yon vrè pouvwa ekonomik mondyal, ki te navige nan direksyon pou yon mache 150 milya dola ...

1 Me 2024

Piblikatè ak OpenAI siyen akò pou kontwole koule enfòmasyon ki trete pa entèlijans atifisyèl

Lendi pase a, Financial Times te anonse yon kontra ak OpenAI. FT bay lisans jounalis mondyal li...

30 Avril 2024