Mitä tulee automaattisiin testeihin tai yksikkötesteihin, millä tahansa ohjelmointikielellä on kaksi vastakkaista mielipidettä:
Joten tällä artikkelilla yritämme vakuuttaa entisen, erityisesti osoittamalla, kuinka helppoa on aloittaa automaattinen testaus Laravelissa.
Puhutaan ensin "miksi" ja sitten katsotaan esimerkkejä miten.
Automaattiset testit suorittavat osia koodista ja raportoivat mahdollisista virheistä. Se on yksinkertaisin tapa kuvata niitä. Kuvittele, että sovelluksessa otetaan käyttöön uusi ominaisuus, jonka jälkeen henkilökohtainen robottiassistentti menisi testaamaan uutta ominaisuutta manuaalisesti ja samalla testaamaan, eikö uusi koodi rikkonut mitään vanhoista ominaisuuksista.
Tämä on tärkein etu: kaikkien ominaisuuksien automaattinen uudelleentestaus. Tämä saattaa tuntua ylimääräiseltä työltä, mutta jos et käske "robottia" tekemään sitä, meidän pitäisi vaihtoehtoisesti tehdä se manuaalisesti, eikö niin?
Tai uusia ominaisuuksia voitaisiin julkaista testaamatta niiden toimivuutta, toivoen, että käyttäjät ilmoittavat virheistä.
Automaattiset testit voivat tarjota meille useita etuja:
Yritä kuvitella sovelluksesi vuoden tai kahden kuluttua, ja tiimissä on uusia kehittäjiä, jotka eivät tiedä aiempina vuosina kirjoitettua koodia tai edes testaamista.
Suorittaaksesi ensimmäisen automaattinen testaus Laravelissa, sinun ei tarvitse kirjoittaa mitään koodia. Kyllä, luit oikein. Kaikki on jo konfiguroitu ja valmisteltu esiasennuksessadefiLaravelin nite, mukaan lukien ensimmäinen perusesimerkki.
Voit yrittää asentaa Laravel-projektin ja suorittaa ensimmäiset testit välittömästi:
laravel new project
cd project
php artisan test
Tämän pitäisi olla tulos konsolissasi:
Jos katsomme esidefiLaravelin ilta /tests
, meillä on kaksi tiedostoa:
testit/Feature/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Sinun ei tarvitse tietää syntaksia ymmärtääksesi mitä täällä tapahtuu: lataa kotisivu ja tarkista, onko tilakoodi HTTP
è "200 OK
".
Tunnetaan myös menetelmän nimellä test_the_application_returns_a_successful_response()
tulee luettavaksi tekstiksi, kun tarkastelet testituloksia, yksinkertaisesti korvaamalla alleviivaussymboli välilyönnillä.
testit/Unit/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_that_true_is_true()
{
$this->assertTrue(true);
}
}
Vaikuttaa vähän turhalta, tarkistaa, onko tämä totta?
Puhumme erityisesti yksikkötesteistä hieman myöhemmin. Toistaiseksi sinun on ymmärrettävä, mitä jokaisessa testissä yleensä tapahtuu.
/tests
on PHP-luokka, joka laajentaa TestCasea PHPUnitRakenteellisesti se on kaikki mitä sinun tarvitsee tietää. Kaikki muu riippuu tarkalleen, mitä asioita haluat testata.
Luodaksesi tyhjän testiluokan, suorita tämä komento:
php artisan make:test HomepageTest
Tiedosto luodaan 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);
}
}
Katsotaan nyt, mitä tapahtuu, jos testiväitteet eivät tuota odotettua tulosta.
Muutetaan esimerkkitestit tällaisiksi:
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);
}
}
Ja nyt, jos suoritamme komennon php artisan test
uudelleen:
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
On olemassa kaksi epäonnistunutta testiä, jotka on merkitty FAIL-merkinnällä. Alla on selitykset ja nuolet osoittavat tarkan epäonnistuneiden testien rivin. Virheet ilmoitetaan tällä tavalla.
Oletetaan, että meillä on lomake ja meidän on testattava erilaisia tapauksia: tarkistamme epäonnistuuko se virheellisillä tiedoilla, tarkistamme onnistuuko se oikealla syötteellä jne.
Virallinen aloituspaketti Kirjailija: Laravel Breeze sisältää i testata sen toimivuutta. Katsotaanpa muutamia esimerkkejä sieltä:
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);
}
}
Tässä meillä on kaksi testiä yhdellä luokalla, koska ne molemmat liittyvät ilmoittautumislomakkeeseen: toinen tarkistaa, onko lomake ladattu oikein ja toinen tarkistaa, toimiiko lähetys hyvin.
Tutustukaamme vielä kahteen menetelmään tuloksen varmentamiseksi, ja vielä kaksi väitettä: $this->assertAuthenticated()
e $response->assertRedirect()
. Voit tarkistaa kaikki saatavilla olevat väitteet virallisesta dokumentaatiosta PHPUnit e Laravelin vastaus . Huomaa, että aiheesta löytyy joitain yleisiä väitteitä $this
, kun taas toiset tarkistavat tietyn $response
reittikutsusta.
Toinen tärkeä asia on use RefreshDatabase;
lause, jossa on viiva, lisätty luokan yläpuolelle. Se on tarpeen, kun testitoimenpiteet voivat vaikuttaa tietokantaan, kuten tässä esimerkissä, loki lisää uuden merkinnän tietokantaan users
tietokantataulukko. Tätä varten sinun tulee luoda erillinen testitietokanta, joka päivitetään php artisan migrate:fresh
aina kun testit suoritetaan.
Sinulla on kaksi vaihtoehtoa: luoda fyysisesti erillinen tietokanta tai käyttää muistissa olevaa SQLite-tietokantaa. Molemmat on määritetty tiedostossa phpunit.xml
tarjotaan oletuksenadefinita kanssa Laravel. Tarvitset erityisesti tämän osan:
<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>
Katso DB_CONNECTION
e DB_DATABASE
ketä kommentoida? Jos sinulla on SQLite palvelimellasi, yksinkertaisin toimenpide on yksinkertaisesti poistaa nämä rivit kommenteista ja testisi suoritetaan muistissa olevaa tietokantaa vastaan.
Tässä testissä sanomme, että käyttäjä tunnistetaan onnistuneesti ja ohjataan oikealle kotisivulle, mutta voimme myös testata tietokannan todellisia tietoja.
Tämän koodin lisäksi:
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
Voimme myös käyttää tietokantatestin väitteet ja tee jotain näin:
$this->assertDatabaseCount('users', 1);
// Or...
$this->assertDatabaseHas('users', [
'email' => 'test@example.com',
]);
Katsotaan nyt toinen esimerkki Laravel Breezen kirjautumissivusta
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();
}
}
Kyse on kirjautumislomakkeesta. Logiikka on samanlainen kuin rekisteröinti, eikö? Mutta kolme menetelmää kahden sijaan, joten tämä on esimerkki sekä hyvien että huonojen skenaarioiden testaamisesta. Joten yleinen logiikka on, että sinun tulee testata molemmat tapaukset: milloin asiat menevät hyvin ja milloin ne epäonnistuvat.
Lisäksi, mitä näet tässä testissä, on käyttö Tietokantatehtaita : Laravel luo väärennetyn käyttäjän ( jälleen päivitetyssä testitietokannassasi ) ja yrittää sitten kirjautua sisään oikeilla tai väärillä tunnuksilla.
Jälleen kerran Laravel luo tehdasesityksendefinita vääriä tietoja varten User
malli, laatikon ulkopuolella.
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),
];
}
}
Katsos, kuinka monta asiaa Laravel itse valmistaa, joten olisiko meidän helppoa aloittaa testaus?
Jos siis toteutamme php artisan test
Laravel Breezen asentamisen jälkeen meidän pitäisi nähdä jotain tällaista:
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
Olet nähnyt alikansiot tests/Feature
e tests/Unit
?.
Mitä eroa niillä on?
Laravel/PHP-ekosysteemin ulkopuolella on maailmanlaajuisesti useita erilaisia automatisoituja testauksia. Voit löytää termejä kuten:
Se kuulostaa monimutkaiselta, ja todelliset erot tämäntyyppisten testien välillä ovat joskus epäselviä. Siksi Laravel on yksinkertaistanut kaikki nämä hämmentävät termit ja ryhmitellyt ne kahteen osaan: yksikkö/ominaisuus.
Yksinkertaisesti sanottuna ominaisuustestit yrittävät suorittaa sovellustesi todelliset toiminnot: hanki URL-osoite, kutsu API, jäljittele tarkkaa toimintaa, kuten lomakkeen täyttämistä. Ominaisuustestit suorittavat yleensä samat tai samankaltaiset toiminnot kuin kuka tahansa projektin käyttäjä tekisi manuaalisesti tosielämässä.
Yksikkötesteillä on kaksi merkitystä. Yleensä saatat huomata, että mitä tahansa automaattista testiä kutsutaan "yksikkötestaukseksi" ja koko prosessia voidaan kutsua "yksikkötestaukseksi". Mutta toiminnallisuuden ja yksikön kontekstissa tässä prosessissa on kyse tietyn ei-julkisen koodiyksikön testaamisesta erikseen. Sinulla on esimerkiksi Laravel-luokka, jossa on menetelmä, joka laskee jotain, kuten tilauksen kokonaishinnan parametreineen. Siksi yksikkötesti ilmoittaisi, palautetaanko kyseisestä menetelmästä (koodiyksiköstä) oikeat tulokset eri parametrein.
Yksikkötestin luomiseksi sinun on lisättävä lippu:
php artisan make:test OrderPriceTest --unit
Luotu koodi on sama kuin yksikköä edeltävä testidefiLaravel järjestelmä:
class OrderPriceTest extends TestCase
{
public function test_example()
{
$this->assertTrue(true);
}
}
Kuten näet, sitä ei ole olemassa RefreshDatabase
, ja tämä on yksi defiyleisimmät yksikkötestimääritykset: se ei kosketa tietokantaa, se toimii "mustana laatikona", eristettynä käynnissä olevasta sovelluksesta.
Yritetään jäljitellä aiemmin mainitsemaani esimerkkiä, kuvitellaan, että meillä on palveluluokka OrderPrice
.
app/Services/OrderPriceService.php:
class OrderPriceService
{
public function calculatePrice($productId, $quantity, $tax = 0.0)
{
// Some kind of calculation logic
}
}
Sitten yksikkötesti voisi näyttää tältä:
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
}
Omakohtaisen kokemukseni mukaan Laravel-projekteista suurin osa testeistä on ominaisuustestejä, ei yksikkötestejä. Ensin sinun on testattava, toimiiko sovelluksesi, niin kuin oikeat ihmiset käyttäisivät sitä.
Seuraavaksi, jos sinulla on erityisiä laskelmia tai logiikkaa, voit definire yksikkönä, parametreilla voit luoda yksikkötestejä erityisesti sitä varten.
Joskus testien kirjoittaminen vaatii itse koodin muokkaamista ja sen uudelleenmuodostamista "testattavammaksi": yksiköiden erottaminen erityisluokiksi tai menetelmiksi.
Mikä on tämän todellinen käyttö php artisan test
, milloin se pitäisi ajaa?
On olemassa erilaisia lähestymistapoja yrityksesi työnkulusta riippuen, mutta yleensä sinun on varmistettava, että kaikki testit ovat "vihreitä" (eli virheettömiä), ennen kuin siirrät lopulliset koodimuutokset arkistoon.
Sitten työskentelet paikallisesti tehtäväsi parissa, ja kun luulet, että olet valmis, suorita testejä varmistaaksesi, ettet ole rikkonut mitään. Muista, että koodisi voi aiheuttaa virheitä paitsi logiikassasi, myös vahingossa rikkoa jonkin muun käyttäytymisen jonkun toisen kauan sitten kirjoitetussa koodissa.
Jos otamme askeleen pidemmälle, se on mahdollista automatisoida monet asioita. Erilaisten CI/CD-työkalujen avulla voit määrittää suoritettavat testit aina, kun joku työntää muutoksia tiettyyn Git-haaraan tai ennen koodin yhdistämistä tuotantohaaraan. Yksinkertaisin työnkulku olisi käyttää Github Actionsia erillinen video joka sen todistaa.
Siitä, kuinka laaja ns. ”testattavuuden” tulisi olla, ollaan eri mieltä: kokeile jokaisella sivulla jokaista mahdollista toimenpidettä ja tapausta tai rajoita työ tärkeimpiin osiin.
Itse asiassa tässä olen samaa mieltä ihmisten kanssa, jotka syyttävät automatisoitua testausta siitä, että se vie enemmän aikaa kuin tuottaa todellista hyötyä. Tämä voi tapahtua, jos kirjoitat testejä jokaisesta yksityiskohdasta. Projektisi saattaa kuitenkin vaatia sitä: pääkysymys on "mikä on mahdollisen virheen hinta".
Toisin sanoen sinun on priorisoitava testausyrityksesi esittämällä kysymys "Mitä tapahtuisi, jos tämä koodi epäonnistuu?" Jos maksujärjestelmässäsi on virheitä, se vaikuttaa suoraan liiketoimintaan. Joten jos roolisi/käyttöoikeutesi toiminnallisuus on rikki, tämä on valtava tietoturvaongelma.
Pidän siitä, miten Matt Stauffer sanoi sen konferenssissa: "Sinun on ensin testattava ne asiat, jotka epäonnistuessaan saisivat sinut irtisanoutumaan työstäsi." Tietysti se on liioittelua, mutta ymmärrät ajatuksen: kokeile ensin tärkeitä asioita. Ja sitten muita ominaisuuksia, jos sinulla on aikaa.
Kaikki yllä olevat esimerkit perustuvat Laravelin esitestaustyökaluundefiiltapäivä: PHPUnit . Mutta vuosien varrella ekosysteemiin on ilmestynyt muita työkaluja, ja yksi viimeisimmistä suosituista on PEST . Laravelin virallisen työntekijän luoma Nuno Maduro , pyrkii yksinkertaistamaan syntaksia, mikä tekee testien koodin kirjoittamisesta entistä nopeampaa.
Konepellin alla se kulkee su PHPUnit, lisäkerroksena, yrittää vain minimoida joitain ennalta toistettuja osiadefiPHPUnit-koodin loppu.
Katsotaanpa esimerkkiä. Muista ominaisuustestiä edeltävä luokkadefinited Laravelissa? Muistutan sinua:
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);
}
}
Tiedätkö miltä sama testi näyttäisi PESTin kanssa?
test('the application returns a successful response')->get('/')->assertStatus(200);
Kyllä, YKSI koodirivi ja siinä se. Joten PESTin tavoitteena on poistaa yleiskustannukset:
Luodaksesi PEST-testin Laravelissa sinun on määritettävä ylimääräinen lippu:
php artisan make:test HomepageTest --pest
Tätä kirjoitettaessa PEST on varsin suosittu Laravel-kehittäjien keskuudessa, mutta on henkilökohtainen valintasi, käytätkö tätä lisätyökalua ja opitko sen syntaksin sekä PHPUnit-huomautuksen.
BlogInnovazione.it
Veeamin Coveware tarjoaa jatkossakin kyberkiristystapahtumien reagointipalveluita. Coveware tarjoaa rikosteknisiä ja korjaavia ominaisuuksia…
Ennakoiva huolto mullistaa öljy- ja kaasualan innovatiivisella ja ennakoivalla lähestymistavalla laitosten hallintaan.…
Britannian CMA on antanut varoituksen Big Techin käyttäytymisestä tekoälymarkkinoilla. Siellä…
Euroopan unionin rakennusten energiatehokkuuden parantamiseksi laatima "Green Houses" -asetus on saanut lainsäädäntöprosessinsa päätökseen…