Wanneer dit kom by outomatiese toetse of eenheidstoetse, in enige programmeertaal, is daar twee opponerende menings:
Dus, met hierdie artikel sal ons eersgenoemde probeer oortuig, veral deur te demonstreer hoe maklik dit is om met outomatiese toetsing in Laravel te begin.
Kom ons praat eers oor die "hoekom", en laat ons dan 'n paar voorbeelde van die hoe sien.
Outomatiese toetse voer dele van die kode uit en rapporteer enige foute. Dit is die eenvoudigste manier om hulle te beskryf. Stel jou voor dat jy 'n nuwe kenmerk in 'n toepassing begin, en dan sal 'n persoonlike robotassistent die nuwe kenmerk handmatig gaan toets, terwyl dit ook toets of die nuwe kode nie enige van die ou kenmerke breek nie.
Dit is die grootste voordeel: hertoets alle kenmerke outomaties. Dit lyk dalk na ekstra werk, maar as jy nie vir die “robot” sê om dit te doen nie, moet ons dit alternatiewelik met die hand doen, reg?
Of nuwe kenmerke kan vrygestel word sonder om te toets of dit werk, met die hoop dat gebruikers foute sal rapporteer.
Outomatiese toetse kan ons verskeie voordele gee:
Probeer om jou toepassing oor 'n jaar of twee voor te stel, met nuwe ontwikkelaars in die span wat nie die kode ken wat in vorige jare geskryf is nie, of selfs hoe om dit te toets.
Om die eerste uit te voer outomatiese toetsing in Laravel, hoef jy geen kode te skryf nie. Ja, jy het reg gelees. Alles is reeds in die vooraf-installasie gekonfigureer en voorbereidefiLaravel, insluitend die heel eerste basiese voorbeeld.
Jy kan probeer om 'n Laravel-projek te installeer en die eerste toetse onmiddellik uit te voer:
laravel new project
cd project
php artisan test
Dit behoort die resultaat in jou konsole te wees:
As ons kyk na die predefinag van Laravel /tests
, ons het twee lêers:
toetse/Feature/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Jy hoef nie enige sintaksis te ken om te verstaan wat hier aangaan nie: laai die tuisblad en kyk of die statuskode HTTP
è "200 OK
".
Ook bekend as die metode naam test_the_application_returns_a_successful_response()
word leesbare teks wanneer jy die toetsresultate bekyk, bloot deur die onderstreepsimbool met 'n spasie te vervang.
tests/Unit/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_that_true_is_true()
{
$this->assertTrue(true);
}
}
Lyk 'n bietjie sinneloos, om te kyk of dit waar is?
Ons sal 'n bietjie later spesifiek oor eenheidstoetse praat. Vir nou moet jy verstaan wat oor die algemeen in elke toets gebeur.
/tests
is 'n PHP-klas wat die TestCase van uitbrei PHPEenheidStruktureel is dit al wat jy moet weet, alles hang af van die presiese dinge wat jy wil toets.
Om 'n leë toetsklas te genereer, voer eenvoudig hierdie opdrag uit:
php artisan make:test HomepageTest
Die lêer word gegenereer 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);
}
}
Kom ons kyk nou wat gebeur as die toetsstellings nie die verwagte resultaat lewer nie.
Kom ons verander die voorbeeldtoetse na hierdie:
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);
}
}
En nou, as ons die opdrag uitvoer php artisan test
weer:
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
Daar is twee mislukte toetse, gemerk as FAIL, met verduidelikings hieronder en pyltjies wat na die presiese lyn van toetse wys wat gedruip het. Foute word op hierdie manier aangedui.
Gestel ons het 'n vorm en ons moet verskeie gevalle toets: ons kyk of dit misluk met ongeldige data, ons kyk of dit met die korrekte invoer slaag, ens.
Die amptelike beginpakket deur Laravel Breeze sluit i die funksionaliteit daarin te toets. Kom ons kyk na 'n paar voorbeelde daarvandaan:
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);
}
}
Hier het ons twee toetse in een klas, aangesien hulle albei verband hou met die registrasievorm: een kyk of die vorm korrek gelaai is en 'n ander kyk of die indiening goed werk.
Kom ons raak vertroud met nog twee metodes om die resultaat te verifieer, nog twee bewerings: $this->assertAuthenticated()
e $response->assertRedirect()
. U kan al die stellings wat beskikbaar is in die amptelike dokumentasie van PHPEenheid e Laravel-reaksie . Let daarop dat sommige algemene bewerings oor die onderwerp voorkom $this
, terwyl ander die spesifieke nagaan $response
vanaf die roete-oproep.
Nog 'n belangrike ding is die use RefreshDatabase;
verklaring, met die beroerte, bo die klas ingevoeg. Dit is nodig wanneer toetsaksies die databasis kan beïnvloed, soos in hierdie voorbeeld, logging voeg 'n nuwe inskrywing in die users
databasis tabel. Hiervoor moet jy 'n aparte toetsdatabasis skep waarmee bygewerk sal word php artisan migrate:fresh
elke keer as die toetse uitgevoer word.
Jy het twee opsies: skep fisies 'n aparte databasis of gebruik 'n in-geheue SQLite databasis. Albei is in die lêer gekonfigureer phpunit.xml
by verstek verskafdefinita met Laravel. Spesifiek, jy benodig hierdie 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>
Sien die DB_CONNECTION
e DB_DATABASE
op watter word kommentaar gelewer? As jy SQLite op jou bediener het, is die eenvoudigste aksie om eenvoudig daardie reëls te ontmerk en jou toetse sal teen daardie in-geheue databasis loop.
In hierdie toets sê ons dat die gebruiker suksesvol geverifieer en na die korrekte tuisblad herlei is, maar ons kan ook die werklike data in die databasis toets.
Benewens hierdie kode:
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
Ons kan ook gebruik die databasistoetsstellings en doen so iets:
$this->assertDatabaseCount('users', 1);
// Or...
$this->assertDatabaseHas('users', [
'email' => 'test@example.com',
]);
Kom ons kyk nou na nog 'n voorbeeld van 'n aanmeldbladsy met 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();
}
}
Dit gaan oor die aanmeldvorm. Die logika is soortgelyk aan registrasie, reg? Maar drie metodes in plaas van twee, so dit is 'n voorbeeld van die toets van beide goeie en slegte scenario's. Dus, die algemene logika is dat jy albei gevalle moet toets: wanneer dinge goed gaan en wanneer dit misluk.
Wat jy ook in hierdie toets sien, is die gebruik van Databasisfabrieke : Laravel skep vals gebruiker ( weer op jou opgedateerde toetsdatabasis ) en probeer dan om aan te meld, met korrekte of verkeerde geloofsbriewe.
Weereens genereer Laravel die fabriek predefinita met vals data vir die User
model, buite die boks.
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),
];
}
}
Jy sien, hoeveel dinge word deur Laravel self voorberei, so sal dit vir ons maklik wees om te begin toets?
So as ons uitvoer php artisan test
nadat ons Laravel Breeze geïnstalleer het, behoort ons iets soos hierdie te sien:
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
Jy het die subgidse gesien tests/Feature
e tests/Unit
?.
Wat is die verskil tussen hulle?
Wêreldwyd, buite die Laravel/PHP-ekosisteem, is daar verskeie tipes outomatiese toetsing. Jy kan terme vind soos:
Dit klink ingewikkeld, en die werklike verskille tussen hierdie tipe toetse is soms vervaag. Daarom het Laravel al hierdie verwarrende terme vereenvoudig en in twee gegroepeer: eenheid/kenmerk.
Eenvoudig gestel, kenmerktoetse probeer om die werklike funksionaliteit van jou toepassings uit te voer: kry die URL, bel die API, boots die presiese gedrag na soos om die vorm in te vul. Kenmerktoetse voer gewoonlik dieselfde of soortgelyke bewerkings uit as wat enige projekgebruiker handmatig in die werklike lewe sou doen.
Eenheidstoetse het twee betekenisse. Oor die algemeen kan jy vind dat enige outomatiese toets "eenheidstoetsing" genoem word en die hele proses kan "eenheidstoetsing" genoem word. Maar in die konteks van funksionaliteit versus eenheid, gaan hierdie proses oor die toets van 'n spesifieke nie-openbare eenheid van kode, in isolasie. Byvoorbeeld, jy het 'n Laravel-klas met 'n metode wat iets bereken, soos die totale bestelprys met parameters. Daarom sal die eenheidstoets aandui of korrekte resultate van daardie metode (kode-eenheid) met verskillende parameters teruggestuur word.
Om 'n eenheidstoets te genereer, moet jy 'n vlag byvoeg:
php artisan make:test OrderPriceTest --unit
Die gegenereerde kode is dieselfde as die pre-eenheid toetsdefiLaravel stelsel:
class OrderPriceTest extends TestCase
{
public function test_example()
{
$this->assertTrue(true);
}
}
Soos jy kan sien, bestaan dit nie RefreshDatabase
, en dit is een van defimees algemene eenheidstoetsdefinisies: dit raak nie aan die databasis nie, dit werk as 'n "swart boks", geïsoleer van die lopende toepassing.
Om die voorbeeld wat ek vroeër genoem het te probeer naboots, laat ons ons verbeel ons het 'n diensklas OrderPrice
.
app/Services/OrderPriceService.php:
class OrderPriceService
{
public function calculatePrice($productId, $quantity, $tax = 0.0)
{
// Some kind of calculation logic
}
}
Dan kan die eenheidstoets iets soos volg lyk:
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
}
In my persoonlike ervaring met Laravel-projekte is die oorgrote meerderheid van die toetse kenmerktoetse, nie eenheidstoetse nie. Eerstens moet jy toets of jou toepassing werk, soos regte mense dit sal gebruik.
Volgende, as jy spesiale berekeninge of logika het, kan jy definire as 'n eenheid, met parameters, kan jy eenheidstoetse spesifiek daarvoor skep.
Soms vereis die skryf van toetse om die kode self te wysig en dit te herfaktoreer om dit meer "toetsbaar" te maak: die eenhede te skei in spesiale klasse of metodes.
Wat is die werklike nut hiervan php artisan test
, wanneer moet jy dit laat loop?
Daar is verskillende benaderings, afhangende van jou besigheidswerkvloei, maar oor die algemeen moet jy seker maak dat alle toetse "groen" is (d.w.s. foutvry) voordat jy die nuutste kodeveranderinge na die bewaarplek stoot.
Dan werk jy plaaslik aan jou taak, en wanneer jy dink jy is klaar, voer 'n paar toetse uit om seker te maak jy het niks gebreek nie. Onthou, jou kode kan foute veroorsaak, nie net in jou logika nie, maar ook onbedoeld ander gedrag in iemand anders se kode wat lank gelede geskryf is, breek.
As ons dit 'n stap verder neem, is dit moontlik om te outomatiseer baie dinge. Met verskeie CI/CD-nutsmiddels kan u toetse spesifiseer wat uitgevoer moet word wanneer iemand veranderinge aan 'n spesifieke Git-tak druk of voordat kode in die produksietak saamgevoeg word. Die eenvoudigste werkvloei sou wees om Github Actions te gebruik, ek het 'n aparte video wat dit bewys.
Daar is verskillende menings oor hoe groot die sogenaamde "toetsdekking" moet wees: probeer elke moontlike bewerking en geval op elke bladsy, of beperk die werk tot die belangrikste dele.
Trouens, dit is waar ek saamstem met mense wat geoutomatiseerde toetsing daarvan beskuldig dat dit meer tyd neem as om werklike voordeel te bied. Dit kan gebeur as jy toetse skryf vir elke detail. Dit gesê, dit kan deur u projek vereis word: die hoofvraag is "wat is die prys van potensiële foute".
Met ander woorde, jy moet jou toetspogings prioritiseer deur die vraag te vra "Wat sal gebeur as hierdie kode misluk?" As jou betalingstelsel foute het, sal dit die besigheid direk beïnvloed. So as die funksionaliteit van jou rolle/toestemmings gebreek is, is dit 'n groot sekuriteitsprobleem.
Ek hou van hoe Matt Stauffer dit by 'n konferensie gestel het: "Jy moet eers daardie dinge toets wat, as hulle misluk, jou van jou werk sou ontslaan." Dit is natuurlik 'n oordrywing, maar jy kry die idee: probeer eers die belangrike goed. En dan ander kenmerke, as jy tyd het.
Al die bogenoemde voorbeelde is gebaseer op die Laravel-voortoetsinstrumentdefinag: PHPEenheid . Maar oor die jare het ander instrumente in die ekosisteem verskyn en een van die nuutste gewilde is PLAAG . Geskep deur amptelike Laravel-werknemer Nuno Maduro , het ten doel om die sintaksis te vereenvoudig, wat die skryf van kode vir toetse selfs vinniger maak.
Onder die enjinkap loop dit su PHPUnit, as 'n bykomende laag, probeer net om sommige voorafherhaalde dele te minimaliseerdefiniteit van die PHPUnit-kode.
Kom ons kyk na 'n voorbeeld. Onthou die voorkenmerktoetsklasdefiin Laravel gesit? Ek sal jou herinner:
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);
}
}
Weet jy hoe dieselfde toets met PEST sou lyk?
test('the application returns a successful response')->get('/')->assertStatus(200);
Ja, EEN reël kode en dit is dit. Dus, die doel van PEST is om die bokoste van:
Om 'n PEST-toets in Laravel te genereer, moet jy 'n bykomende vlag spesifiseer:
php artisan make:test HomepageTest --pest
Soos hierdie skrywe is, is PEST baie gewild onder Laravel-ontwikkelaars, maar dit is jou persoonlike voorkeur of jy hierdie bykomende instrument moet gebruik en die sintaksis daarvan moet leer, sowel as 'n PHPUnit-noot.
BlogInnovazione.it
Die ontwikkeling van fyn motoriese vaardighede deur inkleur berei kinders voor vir meer komplekse vaardighede soos skryf. Om in te kleur...
Die vlootsektor is 'n ware globale ekonomiese moondheid, wat na 'n 150 miljard-mark navigeer het ...
Verlede Maandag het die Financial Times 'n ooreenkoms met OpenAI aangekondig. FT lisensieer sy wêreldklas-joernalistiek ...
Miljoene mense betaal vir stromingsdienste en betaal maandelikse intekengeld. Dit is algemene opinie dat jy...