Testdrevet utvikling med Laravel & Doctrine

Som PHP-utvikler kan du bruke testdrevet utvikling (TDD) -teknikken til å utvikle programvaren ved å skrive tester. Typisk vil TDD dele hver oppgave av utviklingen i individuelle enheter. En test er da skrevet for å sikre at enheten oppfører seg som forventet.

Hvert prosjekt som bruker testdrevet utvikling følger tre enkle trinn gjentatte ganger:

  • Skriv en test for neste bit av funksjonalitet du vil legge til.
  • Skriv funksjonskoden til testen går.
  • Refactor både ny og gammel kode for å gjøre det godt strukturert.

Fortsett å sykle gjennom disse tre trinnene, en test av gangen, bygge opp funksjonaliteten til systemet. Testing vil hjelpe deg med å refactor, som gjør at du kan forbedre designet ditt over tid og gjør noen designproblemer mer opplagte.

Tester som inneholder små individuelle komponenter kalles enhetstester. Mens enhetstester kan utføres uavhengig, hvis du tester noen av komponentene når de er integrert med andre komponenter, gjør du det integreringstesting. Den tredje typen testing er teststubber. Teststubber lar deg teste koden din uten å måtte lage ekte anrop til en database.

Hvorfor TDD fungerer

I dag, som du kan bruke moderne PHP IDE syntaks, er tilbakemelding ikke en stor sak. En av de viktige aspektene ved utviklingen er at du sørger for at koden gjør hva du forventer at den skal gjøre. Siden programvare er komplisert (ulike komponenter integrert med hverandre), ville det være vanskelig for alle våre forventninger å bli oppfylt. Spesielt på slutten av prosjektet, på grunn av din utvikling, vil prosjektet bli mer komplekst og dermed vanskeligere å feilsøke og teste.

TDD bekrefter at koden gjør hva du forventer at den skal gjøre. Hvis noe går galt, er det bare noen få linjer med kode som skal kontrolleres. Feil er lett å finne og fikse. I TDD fokuserer testen på atferden, ikke gjennomføringen. TDD gir påvist kode som er testet, designet og kodet.

PHPUnit & Laravel

PHPUnit er de-facto-standarden for enhetstesting av PHP. Det er egentlig et rammeverk for å skrive tester og gi verktøyene du trenger for å kjøre tester og analysere resultatene. PHPUnit har sin struktur og funksjonalitet fra Kent Becks SUnit.

Det er flere forskjellige påstander som kan hjelpe deg med å teste resultatene av alle slags samtaler i dine applikasjoner. Noen ganger må du være litt mer kreativ for å teste et mer komplekst funksjonsstykke, men påstandene fra PHPUnit dekker de fleste tilfeller du vil teste. Her er en liste over noen av de mest vanlige som du vil finne deg selv i tester:

  • AssertTrue: Kontroller inngangen for å verifisere at den er ekte.
  • AssertFalse: Kontroller at inngangen for å verifisere den er lik falsk verdi.
  • AssertEquals: Kontroller resultatet mot en annen inngang for en kamp.
  • AssertArrayHasKey (): Rapporterer en feil hvis array ikke har nøkkelen.
  • AssertGreaterThan: Kontroller resultatet for å se om det er større enn en verdi.
  • AssertContains: Kontroller at inngangen inneholder en viss verdi.
  • AssertType: Kontroller at en variabel er av en bestemt type.
  • AssertNull: Kontroller at en variabel er null.
  • AssertFileExists: Kontroller at det finnes en fil.
  • AssertRegExp: Kontroller inngangen mot et regulært uttrykk.

Som standard er PHPUnit 4.0 installert i Laravel, og du kan kjøre følgende kommando for å oppdatere den:

bash komponist global krever "phpunit / phpunit = 5.0. *"

De phpunit.xml fil i Laravel rotkatalogen lar deg gjøre noen konfigurasjoner. I dette tilfellet, hvis du vil overstyre standardkonfigurasjonen, kan du redigere filen:

"xml

./ tester / app /

"

Som du ser i koden ovenfor, har jeg lagt til prøven (ikke brukt i artikkelen) i databasekonfigurasjonen.

Hva er Lære ORM?

Læren er en ORM som implementerer data mapper mønsteret og lar deg gjøre en ren adskillelse av programmets forretningsregler fra databasenes utholdenhetslag. For å sette opp doktrinen, er det en bro for å tillate samsvar med Laravel 5s eksisterende konfigurasjon. For å installere Lære 2 i Laravel-prosjektet, kjører vi følgende kommando:

bash komponist krever laravel-doktrin / orm

Som vanlig skal pakken legges til app / config.php, som tjenesteleverandør:

php LaravelDoctrine \ ORM \ DoctrineServiceProvider :: klasse,

Aliaset skal også konfigureres:

php 'EntityManager' => LaravelDoctrine \ ORM \ Fasader \ EntityManager :: klassen

Endelig publiserer vi pakke konfigurasjonen med:

bash php artisan leverandør: publiser - tag = "config"

Hvordan teste læresamlinger

Før noe annet, bør du vite om inventar. Fixtures brukes til å laste inn et kontrollert sett med data i en database, som vi trenger for testing. Heldigvis har Lære 2 et bibliotek for å hjelpe deg med å skrive inventar for Lære ORM.

For å installere fixturesbuntet i Laravel App, må vi kjøre følgende kommando:

bash komponist krever - dv lærdomme / doktrin-fixtures-bunt

La oss lage vår armatur i tester / Fixtures.php:

"php namespace Test, bruk doktrin \ Common \ Persistence \ ObjectManager; bruk doktrin \ Common \ DataFixtures \ FixtureInterface; bruk app \ Entity \ Post;

Klassifiseringsverktøy implementerer FixtureInterface / ** * Last inn innleggsinnstillingene * @param ObjectManager $ manager * @return void * / offentlig funksjonsbelastning (ObjectManager $ manager) $ Post = ny post (['title' => 'hei verden' , 'body' => 'dette er kropp']); $ Manager-> vedvare ($ Post); $ Manager-> flush ();

"

Som du ser, bør armaturklassen din implementere FixtureInterface og burde ha load (ObjectManager $ manager) metode. Lære2-inventar er PHP-klasser der du kan lage objekter og vedvare dem i databasen. For å autoload våre inventar i Laravel, må vi endre composer.json i vår Laravel-rot:

json ... "autoload-dev": "klassekart": ["tester / TestCase.php", "tester / Fixtures.php" // lagt til her], ...

Kjør deretter:

bash komponist dump-autoload

La oss lage vår testfil i testkatalogen DoctrineTest.php.

"php namespace Test, bruk App, bruk App \ Entity \ Post, bruk doktrin \ Common \ DataFixtures \ Executor \ ORMExecutor; bruk doktrin \ Common \ DataFixtures \ Purger \ ORMPurger; bruk doktrin \ Common \ DataFixtures \ Loader; bruk App \ Repository \ PostRepo;

klasselæreTest utvider TestCase private $ em; privat $ repository; privat $ loader; offentlig funksjon setUp () foreldre :: setUp (); $ this-> em = App :: make ('Lære \ ORM \ EntityManagerInterface'); $ this-> repository = new PostRepo ($ this-> em); $ this-> executor = ny ORMExecutor ($ this-> em, ny ORMPurger); $ this-> loader = new Loader; $ this-> loader-> addFixture (new Fixtures);

/ ** @test * / offentlig funksjon post () $ purger = ny ORMPurger (); $ executor = ny ORMExecutor ($ this-> em, $ purger); $ Executor-> utføre ($ dette-> loader-> getFixtures ()); $ user = $ this-> repository-> PostOfTitle ('hej verden'); $ Dette-> em> klart (); $ this-> assertInstanceOf ('App \ Entity \ Post', $ bruker);  "

I SETUP () metode, jeg instantiate the ORMExecutor og lasteren. Vi laster også inn inventar klasse vi nettopp implementert.

Ikke glem at / ** @test * / annotering er svært viktig, og uten dette vil phpunit returnere a Ingen tester funnet i klassen feil.

For å begynne å teste i prosjektrotten, bare kjør kommandoen:

bash sudo phpunit

Resultatet ville være:

"bash PHPUnit 4.6.6 av Sebastian Bergmann og bidragsytere.

Konfigurasjon leses fra /var/www/html/laravel/phpunit.xml. Tid: 17.06 sekunder, Minne: 16.00M OK (1 test, 1 påstand) "

Hvis du vil dele objekter mellom inventar, er det mulig å enkelt legge til en referanse til det objektet ved navn og senere referere det til en relasjon. Her er et eksempel:

"php namespace Test, bruk doktrin \ Common \ Persistence \ ObjectManager; bruk doktrin \ Common \ DataFixtures \ FixtureInterface; bruk app \ Entity \ Post;

klasse PostFixtures implementerer FixtureInterface / ** * Laster brukerens innstillinger * * @param ObjectManager $ manager * @return void * / offentlig funksjon last (ObjectManager $ manager) $ postOne = nytt innlegg (['title' => 'hallo' , 'body' => 'dette er kropp']); $ postTwo = nytt innlegg (['title' => 'hei der', 'body' => 'dette er kropp to']); $ Manager-> vedvare ($ postOne); $ Manager-> vedvare ($ postTwo); $ Manager-> flush ();

 // Store referanse til admin rolle for Brukerrelasjon til Rolle $ this-> addReference ('new-post', $ postOne);  "

og kommentaren fixtur:

"php namespace Test, bruk doktrin \ Common \ Persistence \ ObjectManager; bruk doktrin \ Common \ DataFixtures \ FixtureInterface; bruk app \ Entity \ Post;

class CommentFixtures implementerer FixtureInterface / ** * Last brukerinnstillingene * * @param ObjectManager $ manager * @return void * / offentlig funksjonsbelastning (ObjectManager $ manager) $ comment = ny kommentar (['title' => 'hei' , 'email' => '[email protected]', 'text' => 'fint innlegg']); $ Kommentar-> setPost ($ dette-> getReference ( 'ny-post')); // last den lagrede referanse $ manager-> vedvarer ($ kommentar); $ Manager-> flush (); // lagre referanse til nytt innlegg for Kommentar forhold til innlegg $ this-> addReference ('new-post', $ postOne); "

Med to metoder av getReference () og setReference (), Du kan dele objekt (er) mellom inventar.

Hvis bestilling av inventar er viktig for deg, kan du enkelt bestille dem med getOrder metode i dine inventar som følger:

php offentlig funksjon getOrder () return 5; // nummer i hvilken rekkefølge å laste inn inventar

Legg merke til at bestillingen er relevant for Loader-klassen.

En av de viktige tingene med armaturer er deres evne til å løse avhengighetsproblemer. Det eneste du trenger å legge til er en metode i fixturen din som jeg gjorde nedenfor:

php public function getDependencies () return array ('Test \ CommentFixtures'); // fixture klasser fixture er avhengig av

Konklusjon

Dette er bare en beskrivelse av testdrevet utvikling med Laravel 5 og PHPUnit. Når du tester på repositorier, er det uunngåelig at du skal slå databasen. I dette tilfellet er læringsarmaturer viktige.