Ko gre za avtomatizirane teste ali teste enot, v katerem koli programskem jeziku obstajata dve nasprotujoči si mnenji:
Torej, s tem člankom bomo poskušali prepričati prvega, predvsem s prikazom, kako enostavno je začeti z avtomatiziranim testiranjem v Laravelu.
Najprej se pogovorimo o "zakaj", nato pa si oglejmo nekaj primerov, kako.
Avtomatski testi izvajajo dele kode in poročajo o morebitnih napakah. Tako bi jih najenostavneje opisali. Predstavljajte si, da bi uvedli novo funkcijo v aplikaciji, nato pa bi osebni robotski pomočnik šel in ročno preizkusil novo funkcijo, hkrati pa preizkusil, ali nova koda ni pokvarila katere od starih funkcij.
To je glavna prednost: samodejno ponovno testiranje vseh funkcij. To se morda zdi dodatno delo, vendar če ne ukažete "robotu", naj to stori, bi morali to narediti ročno, kajne?
Ali pa bi lahko izdali nove funkcije, ne da bi preizkusili, ali delujejo, v upanju, da bodo uporabniki poročali o napakah.
Avtomatski testi nam lahko prinesejo številne prednosti:
Poskusite si predstavljati svojo aplikacijo čez leto ali dve, z novimi razvijalci v ekipi, ki ne poznajo kode, napisane v prejšnjih letih, ali celo, kako jo preizkusiti.
Za izvedbo prvega avtomatizirano testiranje v Laravelu, vam ni treba napisati nobene kode. Da, prav ste prebrali. Vse je že konfigurirano in pripravljeno v prednamestitvidefinite of Laravel, vključno s prvim osnovnim primerom.
Lahko poskusite namestiti projekt Laravel in takoj zaženete prve teste:
laravel new project
cd project
php artisan test
To bi moral biti rezultat v vaši konzoli:
Če pogledamo preddefikonec Laravela /tests
, imamo dve datoteki:
testi/Feature/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Ni vam treba poznati sintakse, da bi razumeli, kaj se tukaj dogaja: naložite domačo stran in preverite, ali koda stanja HTTP
è "200 OK
".
Znano tudi kot ime metode test_the_application_returns_a_successful_response()
postane berljivo besedilo, ko si ogledate rezultate testa, preprosto tako, da podčrtani simbol zamenjate s presledkom.
testi/Enota/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_that_true_is_true()
{
$this->assertTrue(true);
}
}
Malo nesmiselno se zdi preverjanje, ali je to res?
O testih enot bomo govorili malo kasneje. Zaenkrat morate razumeti, kaj se običajno zgodi v vsakem testu.
/tests
je razred PHP, ki razširja TestCase of PHPUnitStrukturno je to vse, kar morate vedeti, vse ostalo je odvisno od natančnih stvari, ki jih želite preizkusiti.
Če želite ustvariti prazen testni razred, preprosto zaženite ta ukaz:
php artisan make:test HomepageTest
Datoteka je ustvarjena 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);
}
}
Poglejmo zdaj, kaj se zgodi, če testne trditve ne vrnejo pričakovanega rezultata.
Spremenimo primer testov v tole:
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);
}
}
In zdaj, če zaženemo ukaz php artisan test
ponovno:
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
Obstajata dva neuspešna preizkusa, označena kot NEUSPEŠNO, s spodnjimi razlagami in puščicami, ki kažejo na natančno linijo neuspešnih testov. Napake so prikazane na ta način.
Recimo, da imamo obrazec in moramo preizkusiti različne primere: preverimo, ali ne uspe z neveljavnimi podatki, preverimo, ali uspe s pravilnim vnosom itd.
Uradni začetni komplet avtor Laravel Breeze vključuje i testiranje funkcionalnosti v njej. Poglejmo nekaj primerov od tam:
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);
}
}
Tukaj imamo dva testa v enem razredu, saj sta oba povezana z obrazcem za registracijo: eden preveri, ali je obrazec pravilno naložen, drugi pa preveri, ali oddaja deluje dobro.
Spoznajmo še dve metodi za preverjanje rezultata, še dve trditvi: $this->assertAuthenticated()
e $response->assertRedirect()
. Vse trditve lahko preverite v uradni dokumentaciji PHPUnit e Odziv Laravel . Upoštevajte, da se na to temo pojavlja nekaj splošnih trditev $this
, drugi pa preverjajo konkretne $response
od klica poti.
Druga pomembna stvar je use RefreshDatabase;
izjava s črto, vstavljeno nad razred. To je potrebno, kadar lahko preizkusna dejanja vplivajo na bazo podatkov, kot v tem primeru beleženje doda nov vnos v users
tabela baze podatkov. Za to bi morali ustvariti ločeno preskusno bazo podatkov, ki bo posodobljena z php artisan migrate:fresh
vsakič, ko se izvajajo testi.
Imate dve možnosti: fizično ustvarite ločeno bazo podatkov ali uporabite bazo podatkov SQLite v pomnilniku. Oba sta konfigurirana v datoteki phpunit.xml
privzetodefinita z Laravel. Natančneje, potrebujete ta del:
<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>
Glej DB_CONNECTION
e DB_DATABASE
katere so komentirane? Če imate na svojem strežniku SQLite, je najenostavnejše dejanje, da preprosto odkomentirate te vrstice in vaši testi se bodo izvajali proti tej bazi podatkov v pomnilniku.
Pri tem testu pravimo, da je uporabnik uspešno overjen in preusmerjen na pravilno domačo stran, lahko pa tudi preizkusimo dejanske podatke v bazi podatkov.
Poleg te kode:
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
Lahko tudi uporabimo preskusne trditve baze podatkov in naredi nekaj takega:
$this->assertDatabaseCount('users', 1);
// Or...
$this->assertDatabaseHas('users', [
'email' => 'test@example.com',
]);
Oglejmo si zdaj še en primer prijavne strani z 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();
}
}
Gre za obrazec za prijavo. Logika je podobna registraciji, kajne? Toda tri metode namesto dveh, zato je to primer testiranja dobrih in slabih scenarijev. Torej je skupna logika, da morate preizkusiti oba primera: ko gredo stvari dobro in ko ne uspejo.
Kar vidite v tem testu, je tudi uporaba Tovarne baz podatkov : Laravel ustvari lažnega uporabnika ( ponovno v vaši posodobljeni preskusni bazi podatkov ) in se nato poskuša prijaviti s pravilnimi ali nepravilnimi poverilnicami.
Še enkrat Laravel ustvari tovarniško predefinita z lažnimi podatki za User
model, zunaj škatle.
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),
];
}
}
Vidite, koliko stvari je pripravil Laravel sam, ali bi nam bilo enostavno začeti s testiranjem?
Če torej izvršimo php artisan test
po namestitvi Laravel Breeze bi morali videti nekaj takega:
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 podmape tests/Feature
e tests/Unit
?.
Kakšna je razlika med njimi?
Globalno, zunaj ekosistema Laravel/PHP, obstaja več vrst avtomatiziranega testiranja. Najdete lahko izraze, kot so:
Sliši se zapleteno in dejanske razlike med temi vrstami testov so včasih zabrisane. Zato je Laravel poenostavil vse te zmedene izraze in jih združil v dva: enota/funkcija.
Preprosto povedano, preizkusi funkcij poskušajo izvesti dejansko funkcionalnost vaših aplikacij: pridobite URL, pokličite API, posnemajte natančno vedenje, kot je izpolnjevanje obrazca. Preizkusi funkcij običajno izvajajo enake ali podobne operacije, kot bi jih ročno v resničnem življenju naredil kateri koli uporabnik projekta.
Preizkusi enot imajo dva pomena. Na splošno boste morda ugotovili, da se kateri koli avtomatizirani test imenuje »testiranje enot«, celoten postopek pa lahko imenujemo »testiranje enot«. Toda v kontekstu funkcionalnosti v primerjavi z enoto gre pri tem procesu za testiranje specifične nejavne enote kode v izolaciji. Na primer, imate razred Laravel z metodo, ki nekaj izračuna, na primer skupno ceno naročila s parametri. Zato bi test enote pokazal, ali ta metoda (enota kode) vrne pravilne rezultate z različnimi parametri.
Če želite ustvariti test enote, morate dodati zastavico:
php artisan make:test OrderPriceTest --unit
Ustvarjena koda je enaka testu pred enotodefiLaravel sistem:
class OrderPriceTest extends TestCase
{
public function test_example()
{
$this->assertTrue(true);
}
}
Kot vidite, ne obstaja RefreshDatabase
, in to je eden od definajpogostejše definicije testa enote: ne dotika se baze podatkov, deluje kot »črna skrinjica«, izolirana od delujoče aplikacije.
Če poskušamo posnemati primer, ki sem ga prej omenil, si predstavljajmo, da imamo servisni razred OrderPrice
.
app/Services/OrderPriceService.php:
class OrderPriceService
{
public function calculatePrice($productId, $quantity, $tax = 0.0)
{
// Some kind of calculation logic
}
}
Nato bi lahko test enote izgledal nekako takole:
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
}
Po mojih osebnih izkušnjah s projekti Laravel je velika večina testov testov funkcij, ne testov enot. Najprej morate preizkusiti, ali vaša aplikacija deluje tako, kot bi jo uporabljali pravi ljudje.
Naprej, če imate posebne izračune ali logiko, lahko definire kot enota, s parametri, lahko ustvarite teste enote posebej za to.
Včasih pisanje testov zahteva spreminjanje same kode in njeno refaktoriranje, da postane bolj »testno«: ločevanje enot v posebne razrede ali metode.
Kakšna je dejanska uporaba tega php artisan test
, kdaj naj ga zaženeš?
Obstajajo različni pristopi, odvisno od vašega poslovnega poteka dela, vendar morate na splošno zagotoviti, da so vsi testi »zeleni« (tj. brez napak), preden potisnete končne spremembe kode v repozitorij.
Nato delate lokalno na svoji nalogi in ko mislite, da ste končali, zaženite nekaj testov, da se prepričate, da niste ničesar pokvarili. Ne pozabite, da lahko vaša koda povzroči napake ne samo v vaši lastni logiki, ampak tudi nenamerno prekine neko drugo vedenje v kodi nekoga drugega, ki je bila napisana že zdavnaj.
Če naredimo še korak naprej, je možna avtomatizacija veliko stvari. Z različnimi orodji CI/CD lahko določite preizkuse, ki se izvajajo vsakič, ko nekdo potisne spremembe v določeno vejo Git ali pred združitvijo kode v produkcijsko vejo. Najenostavnejši potek dela bi bil uporaba Github Actions, kar imam ločen video kar dokazuje.
Obstajajo različna mnenja o tem, kako velika naj bi bila tako imenovana "testna pokritost": poskusite vsako možno operacijo in primer na vsaki strani ali omejite delo na najpomembnejše dele.
Pravzaprav se tukaj strinjam z ljudmi, ki avtomatizirano testiranje obtožujejo, da vzame več časa, kot da prinese dejansko korist. To se lahko zgodi, če pišete teste za vsako podrobnost. Kljub temu to morda zahteva vaš projekt: glavno vprašanje je "kakšna je cena morebitne napake".
Z drugimi besedami, določiti morate prednost pri testiranju tako, da postavite vprašanje "Kaj bi se zgodilo, če ta koda ne uspe?" Če ima vaš plačilni sistem napake, bo to neposredno vplivalo na poslovanje. Torej, če je funkcionalnost vaših vlog/dovoljenj pokvarjena, je to velika varnostna težava.
Všeč mi je, kako je Matt Stauffer povedal na konferenci: "Najprej morate preizkusiti tiste stvari, zaradi katerih bi vas, če ne uspejo, odpustili iz službe." Seveda je to pretiravanje, vendar razumete: najprej poskusite pomembne stvari. In potem druge funkcije, če imate čas.
Vsi zgornji primeri temeljijo na orodju za predhodno testiranje Laraveldefinoč: PHPUnit . Toda z leti so se v ekosistemu pojavila druga orodja in eno najnovejših priljubljenih je ŠKODLJIVCA . Ustvaril uradni uslužbenec Laravela Nuno Maduro , želi poenostaviti sintakso, zaradi česar je pisanje kode za teste še hitrejše.
Pod pokrovom motorja teče su PHPUnit, kot dodatna plast, samo poskuša minimizirati nekatere vnaprej ponovljene deledefikonca kode PHPUnit.
Poglejmo si primer. Ne pozabite na razred predhodnega preizkusa funkcijdefini v Laravelu? Spomnil vas bom:
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);
}
}
Ali veste, kako bi izgledal isti test s PEST?
test('the application returns a successful response')->get('/')->assertStatus(200);
Da, ENA vrstica kode in to je to. Torej, cilj PEST je odstraniti režijske stroške:
Če želite ustvariti test PEST v Laravelu, morate določiti dodatno zastavico:
php artisan make:test HomepageTest --pest
Od tega pisanja je PEST precej priljubljen med razvijalci Laravel, vendar je vaša osebna želja, ali boste uporabili to dodatno orodje in se naučili njegove sintakse ter opombe PHPUnit.
BlogInnovazione.it
Prejšnji ponedeljek je Financial Times objavil dogovor z OpenAI. FT licencira svoje vrhunsko novinarstvo ...
Milijoni ljudi plačujejo storitve pretakanja in plačujejo mesečne naročnine. Splošno mnenje je, da si…
Coveware by Veeam bo še naprej zagotavljal storitve odzivanja na incidente kibernetskega izsiljevanja. Coveware bo nudil forenziko in zmogljivosti sanacije ...
Prediktivno vzdrževanje revolucionira sektor nafte in plina z inovativnim in proaktivnim pristopom k upravljanju obratov.…