As it giet om automatisearre tests as ienheidstests, yn elke programmeartaal, binne d'r twa tsjinoerstelde mieningen:
Dat, mei dit artikel sille wy besykje de eardere te oertsjûgjen, foaral troch te demonstrearjen hoe maklik it is om te begjinnen mei automatisearre testen yn Laravel.
Litte wy earst prate oer it "wêrom", en dan litte wy wat foarbylden sjen fan it hoe.
Automatisearre tests rinne dielen fan 'e koade en rapportearje alle flaters. Dat is de maklikste manier om se te beskriuwen. Stel jo foar dat jo in nije funksje yn in app útrolje, en dan soe in persoanlike robotassistint gean en de nije funksje manuell testje, wylst jo ek testen oft de nije koade gjin fan 'e âlde funksjes brekt.
Dit is it wichtichste foardiel: alle funksjes automatysk opnij testen. Dit kin lykje as ekstra wurk, mar as jo de "robot" net sizze om it te dwaan, moatte wy it alternatyf mei de hân dwaan, toch?
Of nije funksjes koene wurde frijjûn sûnder te testen oft se wurkje, yn 'e hoop dat brûkers bugs sille melde.
Automatisearre tests kinne ús ferskate foardielen jaan:
Besykje jo applikaasje yn in jier as twa foar te stellen, mei nije ûntwikkelders yn it team dy't de koade net kenne dy't yn foargeande jierren is skreaun, of sels hoe't jo it kinne testen.
Om útfiere de earste automatisearre testen yn Laravel, jo hoege gjin koade te skriuwen. Ja, jo lêze dat goed. Alles is al konfigureare en taret yn 'e pre-ynstallaasjedefinite of Laravel, ynklusyf it alderearste basisfoarbyld.
Jo kinne besykje in Laravel-projekt te ynstallearjen en de earste testen fuortendaliks útfiere:
laravel new project
cd project
php artisan test
Dit moat it resultaat wêze yn jo konsole:
As wy nimme in blik op de predefinacht fan Laravel /tests
, wy hawwe twa triemmen:
tests/Feature/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Jo hoege gjin syntaksis te witten om te begripen wat hjir bart: lade de thússide en kontrolearje oft de statuskoade HTTP
is "200 OK
".
Ek bekend as de metoade namme test_the_application_returns_a_successful_response()
wurdt lêsbere tekst as jo de testresultaten besjen, gewoan troch it ûnderstreksymboal te ferfangen troch in spaasje.
tests/Unit/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_that_true_is_true()
{
$this->assertTrue(true);
}
}
It liket in bytsje nutteloos, kontrolearje om te sjen oft dit wier is?
Wy sille in bytsje letter spesifyk prate oer ienheidstests. Foar no moatte jo begripe wat yn 't algemien bart yn elke test.
/tests
is in PHP klasse dy't wreidet de TestCase fan PHPUnitStruktureel is dat alles wat jo witte moatte, al it oare hinget ôf fan 'e krekte dingen dy't jo wolle testen.
Om in lege testklasse te generearjen, útfiere gewoan dit kommando:
php artisan make:test HomepageTest
De triem wurdt oanmakke 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);
}
}
Litte wy no sjen wat der bart as de testbewearingen it ferwachte resultaat net werombringe.
Litte wy de foarbyldtests feroarje nei dit:
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 no, as wy it kommando útfiere php artisan test
wer:
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
D'r binne twa mislearre tests, markearre as FAIL, mei taljochtingen hjirûnder en pylken dy't wize op de krekte line fan tests dy't mislearre. Flaters wurde op dizze manier oanjûn.
Stel dat wy in formulier hawwe en wy moatte ferskate gefallen testen: wy kontrolearje oft it mislearret mei ûnjildige gegevens, wy kontrolearje oft it slagget mei de juste ynfier, ensfh.
De offisjele starterspakket troch Laravel Breeze omfettet i it testen fan de funksjonaliteit dêryn. Litte wy dêr wat foarbylden fan sjen:
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);
}
}
Hjir hawwe wy twa tests yn ien klasse, om't se beide relatearre binne oan it registraasjeformulier: ien kontrolearret as it formulier goed laden is en in oare kontrolearret as it yntsjinjen goed wurket.
Lit ús fertroud wurde mei noch twa metoaden foar it ferifiearjen fan it resultaat, noch twa bewearingen: $this->assertAuthenticated()
e $response->assertRedirect()
. Jo kinne kontrolearje alle bewearingen beskikber yn de offisjele dokumintaasje fan PHPUnit e LaravelResponse . Tink derom dat guon algemiene bewearingen oer it ûnderwerp foarkomme $this
, wylst oaren kontrolearje de spesifike $response
út de rûte oprop.
In oar wichtich ding is de use RefreshDatabase;
statement, mei de slach, ynfoege boppe de klasse. It is nedich as testaksjes de databank kinne beynfloedzje, lykas yn dit foarbyld, logging foeget in nije yngong ta yn 'e users
databank tabel. Hjirfoar moatte jo in aparte testdatabase meitsje wêrmei't jo bywurke wurde php artisan migrate:fresh
elke kear as de tests wurde útfierd.
Jo hawwe twa opsjes: fysyk meitsje in aparte databank of brûk in yn-ûnthâld SQLite databank. Beide binne konfigurearre yn it bestân phpunit.xml
standert foarsjoendefinit mei Laravel. Spesifyk hawwe jo dit diel nedich:
<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>
Sjoch de DB_CONNECTION
e DB_DATABASE
op hokker wurde kommentearre? As jo SQLite op jo tsjinner hawwe, is de ienfâldichste aksje om dizze rigels gewoan unkommentearje te litten en jo tests sille rinne tsjin dy databank yn it ûnthâld.
Yn dizze test sizze wy dat de brûker mei súkses authentisearre is en omlaat nei de juste thússide, mar wy kinne ek de eigentlike gegevens yn 'e databank testen.
Neist dizze koade:
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
Wy kinne ek brûke de databank test bewearingen en doch sa'n ding:
$this->assertDatabaseCount('users', 1);
// Or...
$this->assertDatabaseHas('users', [
'email' => 'test@example.com',
]);
Litte wy no in oar foarbyld sjen fan in oanmeldside mei 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();
}
}
It giet om it oanmeldformulier. De logika is gelyk oan registraasje, krekt? Mar trije metoaden ynstee fan twa, dus dit is in foarbyld fan it testen fan sawol goede as minne senario's. Dat, de mienskiplike logika is dat jo beide gefallen moatte testen: wannear't dingen goed gean en wannear't se mislearje.
Ek, wat jo sjogge yn dizze test is it gebrûk fan Databank Fabriken : Laravel makket falske brûker ( wer, op jo bywurke test databank ) en besiket dan oan te melden, mei juste of ferkearde referinsjes.
Wer genereart Laravel it fabryk predefinita mei falske gegevens foar de User
model, bûten de doaze.
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),
];
}
}
Jo sjogge, hoefolle dingen wurde taret troch Laravel sels, dus soe it foar ús maklik wêze om te testen?
Dus as wy útfiere php artisan test
nei it ynstallearjen fan Laravel Breeze, soene wy sokssawat moatte sjen:
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
Jo hawwe de submappen sjoen tests/Feature
e tests/Unit
?.
Wat is it ferskil tusken harren?
Wrâldwiid, bûten it Laravel / PHP-ekosysteem, binne d'r ferskate soarten automatisearre testen. Jo kinne termen fine lykas:
It klinkt yngewikkeld, en de eigentlike ferskillen tusken dizze soarten testen binne soms nuansearre. Dêrom hat Laravel al dizze betiizjende termen ferienfâldige en groepearre yn twa: ienheid / funksje.
Simpelwei, funksjetests besykje de eigentlike funksjonaliteit fan jo applikaasjes út te fieren: krije de URL, skilje de API, mimik it krekte gedrach lykas it ynfoljen fan it formulier. Funksjetests fiere normaal deselde of ferlykbere operaasjes út as elke projektbrûker soe dwaan, mei de hân, yn it echte libben.
Ienheidstests hawwe twa betsjuttingen. Yn 't algemien kinne jo fine dat elke automatisearre test "ienheidstesten" wurdt neamd en it heule proses kin "ienheidstesten" wurde neamd. Mar yn 'e kontekst fan funksjonaliteit tsjin ienheid giet dit proses oer it testen fan in spesifike net-iepenbiere ienheid fan koade, yn isolemint. Jo hawwe bygelyks in Laravel-klasse mei in metoade dy't wat berekkent, lykas de totale oarderpriis mei parameters. Dêrom soe de ienheidstest oanjaan oft juste resultaten wurde weromjûn fan dy metoade (koade-ienheid), mei ferskate parameters.
Om in ienheidstest te generearjen, moatte jo in flagge tafoegje:
php artisan make:test OrderPriceTest --unit
De oanmakke koade is itselde as de pre-ienheidstestdefiLaravel systeem:
class OrderPriceTest extends TestCase
{
public function test_example()
{
$this->assertTrue(true);
}
}
Sa't jo sjen kinne, it bestiet net RefreshDatabase
, en dit is ien fan defimeast foarkommende ienheidstestdefinysjes: it rekket de databank net, it wurket as in "swarte doaze", isolearre fan 'e rinnende applikaasje.
Besykje it foarbyld te imitearjen dat ik earder neamde, lit ús yntinke dat wy in tsjinstklasse hawwe OrderPrice
.
app/Services/OrderPriceService.php:
class OrderPriceService
{
public function calculatePrice($productId, $quantity, $tax = 0.0)
{
// Some kind of calculation logic
}
}
Dan kin de ienheidstest der sa útsjen:
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
}
Yn myn persoanlike ûnderfining mei Laravel-projekten binne de grutte mearderheid fan testen Featuretests, net Unit-tests. Earst moatte jo testen oft jo applikaasje wurket, lykas echte minsken it soene brûke.
Folgjende, as jo spesjale berekkeningen of logika hawwe kinne jo definire as ienheid, mei parameters, kinne jo meitsje ienheid tests spesifyk foar dat.
Soms fereasket it skriuwen fan tests it feroarjen fan de koade sels en it refactoring it om it mear "testber" te meitsjen: de ienheden skieden yn spesjale klassen as metoaden.
Wat is it eigentlike gebrûk fan dit php artisan test
, wannear moatte jo rinne it?
D'r binne ferskate oanpak, ôfhinklik fan jo saaklike workflow, mar oer it algemien moatte jo derfoar soargje dat alle testen "grien" binne (dus flaterfrij) foardat jo de lêste koadewizigingen nei it repository triuwe.
Dan wurkje jo lokaal oan jo taak, en as jo tinke dat jo klear binne, útfiere wat tests om te soargjen dat jo neat hawwe brutsen. Unthâld, jo koade kin bugs net allinich yn jo eigen logika feroarsaakje, mar ek ûnbedoeld wat oar gedrach brekke yn 'e koade fan in oar dy't lang lyn skreaun is.
As wy it in stap fierder nimme, is it mooglik om te automatisearjen folle dingen. Mei ferskate CI / CD-ark, kinne jo testen opjaan om te rinnen as immen wizigingen nei in spesifike Git-tûke triuwt of foardat jo koade gearfoegje yn 'e produksjetûke. De ienfâldichste workflow soe wêze om Github Actions te brûken, haw ik in aparte fideo dy't it bewiist.
D'r binne ferskate mieningen oer hoe grut de saneamde "testdekking" moat wêze: besykje elke mooglike operaasje en saak op elke side, of behein it wurk ta de wichtichste dielen.
Yn feite is dit wêr't ik it iens is mei minsken dy't automatisearre testen beskuldigje dat se mear tiid nimme dan it feitlik foardiel leverje. Dit kin barre as jo tests skriuwe foar elk detail. Dat sei, it kin ferplicht wurde troch jo projekt: de wichtichste fraach is "wat is de priis fan potinsjele flater".
Mei oare wurden, jo moatte jo testepogings prioritearje troch de fraach te stellen "Wat soe barre as dizze koade mislearre?" As jo betellingssysteem bugs hat, sil it direkt ynfloed hawwe op it bedriuw. Dus as de funksjonaliteit fan jo rollen / tagongsrjochten is brutsen, is dit in enoarm feiligensprobleem.
Ik fyn it leuk hoe't Matt Stauffer it op in konferinsje stelde: "Jo moatte earst dy dingen testen dy't, as se mislearje, jo fan jo baan ûntslein wurde." Dat is fansels in oerdriuwing, mar jo krije it idee: besykje earst de wichtige dingen. En dan oare funksjes, as jo tiid hawwe.
Alle boppesteande foarbylden binne basearre op Laravel pre testing arkdefinacht: PHPUnit . Mar yn 'e rin fan' e jierren binne oare ark yn it ekosysteem ferskynd en ien fan 'e lêste populêre is PEST . Makke troch offisjele Laravel-meiwurker Nuno Maduro , hat as doel de syntaksis te ferienfâldigjen, wêrtroch it skriuwen fan koade foar tests noch flugger makket.
Under de motorkap rint it su PHPUnit, as in ekstra laach, gewoan besykje wat foarôf werhelle dielen te minimalisearjendefinite fan de PHPUnit-koade.
Litte wy nei in foarbyld sjen. Unthâld de pre funksje test klassedefiniget yn Laravel? Ik sil dy ûnthâlde:
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);
}
}
Witte jo hoe't deselde test der útsjen soe mei PEST?
test('the application returns a successful response')->get('/')->assertStatus(200);
Ja, ONE rigel koade en dat is it. Dat, it doel fan PEST is om de overhead fan:
Om in PEST-test yn Laravel te generearjen, moatte jo in ekstra flagge opjaan:
php artisan make:test HomepageTest --pest
Op dit stuit is PEST frij populêr ûnder Laravel-ûntwikkelders, mar it is jo persoanlike foarkar of jo dit ekstra ark brûke moatte en syn syntaksis leare, lykas ek in PHPUnit-notysje.
BlogInnovazione.it
In ophthalmoplasty-operaasje mei de Apple Vision Pro kommersjele werjouwer waard útfierd by de Catania Polyclinic ...
It ûntwikkeljen fan fynmotoryske feardigens troch kleurjen taret bern op mear komplekse feardigens lykas skriuwen. Kleurje...
De marinesektor is in wiere wrâldwide ekonomyske macht, dy't navigearre is nei in merk fan 150 miljard ...
Ofrûne moandei kundige de Financial Times in deal oan mei OpenAI. FT lisinsje har sjoernalistyk fan wrâldklasse ...