Pokiaľ ide o automatizované testy alebo jednotkové testy, v akomkoľvek programovacom jazyku existujú dva protichodné názory:
Takže týmto článkom sa pokúsime presvedčiť tých prvých, najmä tým, že ukážeme, aké ľahké je začať s automatizovaným testovaním v Laravel.
Najprv si povedzme o „prečo“ a potom si pozrime niekoľko príkladov ako.
Automatizované testy spúšťajú časti kódu a hlásia všetky chyby. To je najjednoduchší spôsob, ako ich opísať. Predstavte si, že v aplikácii spustíte novú funkciu a potom by šiel osobný robotický asistent manuálne otestovať novú funkciu a zároveň by testoval, či nový kód neporušil niektorú zo starých funkcií.
Toto je hlavná výhoda: automatické opätovné testovanie všetkých funkcií. Môže sa to zdať ako práca navyše, ale ak nepoviete „robotovi“, aby to urobil, mali by sme to urobiť manuálne, však?
Alebo nové funkcie môžu byť uvoľnené bez testovania, či fungujú, dúfajúc, že používatelia budú hlásiť chyby.
Automatizované testy nám môžu poskytnúť niekoľko výhod:
Skúste si predstaviť svoju aplikáciu o rok alebo dva, s novými vývojármi v tíme, ktorí nepoznajú kód napísaný v predchádzajúcich rokoch, ani nepoznajú, ako ho otestovať.
Na vykonanie prvého automatizované testovanie v Laravel, nemusíte písať žiadny kód. Áno, čítate správne. Všetko je už nakonfigurované a pripravené v predinštaláciidefinite of Laravel, vrátane úplne prvého základného príkladu.
Môžete skúsiť nainštalovať projekt Laravel a okamžite spustiť prvé testy:
laravel new project
cd project
php artisan test
Toto by mal byť výsledok vo vašej konzole:
Ak sa pozrieme na preddefimiesto Laravelu /tests
, máme dva súbory:
testy/Feature/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Nepotrebujete poznať žiadnu syntax, aby ste pochopili, čo sa tu deje: načítajte domovskú stránku a skontrolujte, či je stavový kód HTTP
è "200 OK
".
Tiež známy ako názov metódy test_the_application_returns_a_successful_response()
sa stane čitateľným textom, keď si prezeráte výsledky testu, jednoducho nahradením symbolu podčiarknutia medzerou.
testy/Unit/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_that_true_is_true()
{
$this->assertTrue(true);
}
}
Zdá sa to trochu zbytočné, overiť si, či je to pravda?
Konkrétne o jednotkových testoch si povieme o niečo neskôr. Zatiaľ musíte pochopiť, čo sa vo všeobecnosti deje v každom teste.
/tests
je trieda PHP, ktorá rozširuje TestCase of PHPUnitŠtrukturálne, to je všetko, čo potrebujete vedieť, všetko ostatné závisí od presných vecí, ktoré chcete testovať.
Ak chcete vygenerovať prázdnu testovaciu triedu, jednoducho spustite tento príkaz:
php artisan make:test HomepageTest
Súbor sa vygeneruje 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);
}
}
Pozrime sa teraz, čo sa stane, ak testovacie tvrdenia nevrátia očakávaný výsledok.
Zmeňme príklady testov na toto:
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);
}
}
A teraz, ak spustíme príkaz php artisan test
opäť:
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
Existujú dva neúspešné testy, označené ako FAIL, s vysvetleniami nižšie a šípkami ukazujúcimi na presný riadok testov, ktoré zlyhali. Chyby sú označené týmto spôsobom.
Predpokladajme, že máme formulár a potrebujeme otestovať rôzne prípady: skontrolujeme, či zlyhá s neplatnými údajmi, skontrolujeme, či uspeje so správnym zadaním atď.
Oficiálna štartovacia súprava od Laravel Breeze zahŕňa i testovanie funkčnosti v ňom. Pozrime sa odtiaľ na niekoľko príkladov:
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);
}
}
Tu máme dva testy v jednej triede, pretože oba súvisia s registračným formulárom: jeden kontroluje, či je formulár načítaný správne a druhý kontroluje, či odoslanie funguje správne.
Zoznámime sa s ďalšími dvoma metódami overenia výsledku, ďalšími dvoma tvrdeniami: $this->assertAuthenticated()
e $response->assertRedirect()
. Môžete skontrolovať všetky dostupné tvrdenia v oficiálnej dokumentácii PHPUnit e Laravelova odpoveď . Všimnite si, že na túto tému sa vyskytujú niektoré všeobecné tvrdenia $this
, zatiaľ čo iní kontrolujú konkrétne $response
z hovoru na trase.
Ďalšou dôležitou vecou je use RefreshDatabase;
vyhlásenie s ťahom, vloženým nad triedu. Je to potrebné, keď testovacie akcie môžu ovplyvniť databázu, ako v tomto príklade, protokolovanie pridá novú položku do users
databázová tabuľka. Na tento účel by ste mali vytvoriť samostatnú testovaciu databázu, ktorá sa bude aktualizovať php artisan migrate:fresh
pri každom spustení testov.
Máte dve možnosti: fyzicky vytvoriť samostatnú databázu alebo použiť in-memory databázu SQLite. Obe sú nakonfigurované v súbore phpunit.xml
poskytované štandardnedefinita s laravel. Konkrétne potrebujete túto časť:
<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>
Pozrite si DB_CONNECTION
e DB_DATABASE
ktoré sú komentované? Ak máte na svojom serveri SQLite, najjednoduchšou akciou je jednoducho odkomentovať tieto riadky a vaše testy sa spustia proti tejto databáze v pamäti.
V tomto teste hovoríme, že používateľ je úspešne autentizovaný a presmerovaný na správnu domovskú stránku, ale môžeme otestovať aj skutočné údaje v databáze.
Okrem tohto kódu:
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
Môžeme použiť aj testovacie tvrdenia databázy a urob niečo takéto:
$this->assertDatabaseCount('users', 1);
// Or...
$this->assertDatabaseHas('users', [
'email' => 'test@example.com',
]);
Pozrime sa teraz na ďalší príklad prihlasovacej stránky s 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();
}
}
Ide o prihlasovací formulár. Logika je podobná registrácii, však? Ale tri metódy namiesto dvoch, takže toto je príklad testovania dobrých aj zlých scenárov. Spoločnou logikou teda je, že by ste mali otestovať oba prípady: keď veci idú dobre, aj keď zlyhajú.
Tiež to, čo vidíte v tomto teste, je použitie Databázové továrne : Laravel vytvára falošného používateľa ( opäť vo vašej aktualizovanej testovacej databáze ) a potom sa pokúsi prihlásiť so správnymi alebo nesprávnymi prihlasovacími údajmi.
Laravel opäť generuje továrenské preddefinita s nepravdivými údajmi pre User
model, mimo krabice.
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),
];
}
}
Vidíte, koľko vecí pripravuje samotný Laravel, takže by bolo pre nás ľahké začať testovať?
Ak teda vykonáme php artisan test
po inštalácii Laravel Breeze by sme mali vidieť niečo takéto:
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
Videli ste podpriečinky tests/Feature
e tests/Unit
?.
Aký je medzi nimi rozdiel?
Globálne, mimo ekosystému Laravel/PHP, existuje niekoľko typov automatizovaného testovania. Môžete nájsť výrazy ako:
Znie to komplikovane a skutočné rozdiely medzi týmito typmi testov sú niekedy rozmazané. Laravel preto všetky tieto mätúce pojmy zjednodušil a zoskupil do dvoch: jednotka/vlastnosť.
Jednoducho povedané, testy funkcií sa pokúšajú spustiť skutočnú funkčnosť vašich aplikácií: získať adresu URL, zavolať rozhranie API, napodobniť presné správanie, ako je vyplnenie formulára. Testy funkcií zvyčajne vykonávajú rovnaké alebo podobné operácie, aké by robil každý používateľ projektu manuálne v reálnom živote.
Jednotkové testy majú dva významy. Vo všeobecnosti môžete zistiť, že každý automatizovaný test sa nazýva „testovanie jednotiek“ a celý proces sa môže nazývať „testovanie jednotiek“. Ale v kontexte funkčnosti verzus jednotka je tento proces o testovaní špecifickej neverejnej jednotky kódu v izolácii. Napríklad máte triedu Laravel s metódou, ktorá niečo vypočíta, napríklad celkovú cenu objednávky s parametrami. Preto by test jednotky uviedol, či sa z tejto metódy (jednotka kódu) vrátia správne výsledky s rôznymi parametrami.
Ak chcete vygenerovať test jednotky, musíte pridať príznak:
php artisan make:test OrderPriceTest --unit
Vygenerovaný kód je rovnaký ako pri teste pred jednotkoudefiLaravel systém:
class OrderPriceTest extends TestCase
{
public function test_example()
{
$this->assertTrue(true);
}
}
Ako vidíte, neexistuje RefreshDatabase
, a toto je jeden z definajbežnejšie definície unit testov: nedotýka sa databázy, funguje ako „čierna skrinka“, izolovaná od spustenej aplikácie.
Snažíme sa napodobniť príklad, ktorý som už spomenul, predstavme si, že máme triedu služieb OrderPrice
.
app/Services/OrderPriceService.php:
class OrderPriceService
{
public function calculatePrice($productId, $quantity, $tax = 0.0)
{
// Some kind of calculation logic
}
}
Potom by test jednotky mohol vyzerať takto:
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
}
Podľa mojich osobných skúseností s projektmi Laravel je veľká väčšina testov testami funkcií, nie testov jednotiek. Najprv musíte otestovať, či vaša aplikácia funguje, ako by ju používali skutoční ľudia.
Ďalej, ak máte špeciálne výpočty alebo logiku, môžete definire ako jednotku, s parametrami, môžete vytvoriť testy jednotiek špeciálne pre tento účel.
Niekedy si písanie testov vyžaduje úpravu samotného kódu a jeho prerobenie, aby bol „testovateľnejší“: rozdelenie jednotiek do špeciálnych tried alebo metód.
Aké je skutočné využitie tohto php artisan test
, kedy by ste to mali spustiť?
Existujú rôzne prístupy v závislosti od vášho obchodného pracovného toku, ale vo všeobecnosti sa musíte uistiť, že všetky testy sú „zelené“ (t. j. bezchybné) pred odoslaním najnovších zmien kódu do úložiska.
Potom na svojej úlohe pracujete lokálne a keď si myslíte, že ste hotový, spustite niekoľko testov, aby ste sa uistili, že ste nič neporušili. Pamätajte, že váš kód môže spôsobiť chyby nielen vo vašej vlastnej logike, ale aj neúmyselne narušiť niektoré iné správanie v kóde niekoho iného napísaného už dávno.
Ak to urobíme o krok ďalej, je možné automatizovať veľa veci. Pomocou rôznych nástrojov CI/CD môžete špecifikovať testy, ktoré sa majú spustiť vždy, keď niekto vloží zmeny do konkrétnej vetvy Git alebo pred zlúčením kódu do produkčnej vetvy. Najjednoduchším pracovným postupom by bolo použiť Github Actions, mám samostatné video čo to dokazuje.
Existujú rôzne názory na to, aké veľké by malo byť takzvané „testovacie pokrytie“: vyskúšajte každú možnú operáciu a prípad na každej stránke alebo obmedzte prácu na najdôležitejšie časti.
V skutočnosti tu súhlasím s ľuďmi, ktorí obviňujú automatické testovanie z toho, že zaberá viac času, než poskytuje skutočný prínos. To sa môže stať, ak píšete testy pre každý jeden detail. To znamená, že to môže vyžadovať váš projekt: hlavnou otázkou je „aká je cena potenciálnej chyby“.
Inými slovami, musíte uprednostniť svoje testovacie úsilie položením otázky „Čo by sa stalo, keby tento kód zlyhal?“ Ak má váš platobný systém chyby, bude to mať priamy vplyv na podnikanie. Ak je teda funkčnosť vašich rolí/oprávnení nefunkčná, ide o veľký bezpečnostný problém.
Páči sa mi, ako to povedal Matt Stauffer na konferencii: „Najskôr musíte otestovať veci, ktoré, ak zlyhajú, vás vyhodia z práce.“ Samozrejme, že je to prehnané, ale máte myšlienku: najskôr vyskúšajte dôležité veci. A potom ďalšie funkcie, ak máte čas.
Všetky vyššie uvedené príklady sú založené na predbežnom testovacom nástroji Laraveldefinoc: PHPUnit . V priebehu rokov sa však v ekosystéme objavili ďalšie nástroje a jedným z najnovších populárnych je PEST . Vytvoril oficiálny zamestnanec Laravel Nuno Maduro , má za cieľ zjednodušiť syntax, vďaka čomu je písanie kódu pre testy ešte rýchlejšie.
Pod kapotou to beží su PHPUnit, ako ďalšia vrstva, sa len snaží minimalizovať niektoré predopakované častidefičasť kódu PHPUnit.
Pozrime sa na príklad. Pamätajte na triedu predbežného testovania funkciídefinited v Laravel? Pripomeniem ti:
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);
}
}
Viete, ako by vyzeral rovnaký test s PEST?
test('the application returns a successful response')->get('/')->assertStatus(200);
Áno, JEDEN riadok kódu a to je všetko. Takže cieľom PEST je odstrániť režijné náklady:
Ak chcete vygenerovať test PEST v Laravel, musíte zadať ďalší príznak:
php artisan make:test HomepageTest --pest
V čase písania tohto článku je PEST medzi vývojármi Laravel pomerne populárny, ale je to vaša osobná preferencia, či použijete tento dodatočný nástroj a naučíte sa jeho syntax, ako aj poznámku PHPUnit.
BlogInnovazione.it
Rozvíjanie jemnej motoriky pomocou vyfarbovania pripravuje deti na zložitejšie zručnosti, ako je písanie. Na farbenie…
Námorný sektor je skutočnou globálnou ekonomickou veľmocou, ktorá smerovala k 150 miliardovému trhu...
Minulý pondelok Financial Times oznámili dohodu s OpenAI. FT licencuje svoju žurnalistiku svetovej triedy…
Milióny ľudí platia za streamovacie služby a platia mesačné predplatné. Je bežný názor, že si…