Bine ați venit în această serie despre dezvoltarea aplicațiilor Laravel utilizând o abordare bazată pe comportament (BDD). Full stack BDD poate părea complicată și intimidantă. Există la fel de multe moduri de a face acest lucru ca și dezvoltatorii.
În această serie, vă voi învăța prin abordarea mea de a utiliza Behat și PhpSpec pentru a proiecta o aplicație Laravel de la zero.
Există multe resurse despre BDD în general, dar materialul specific Laravel este greu de găsit. Prin urmare, în această serie, ne vom concentra mai mult pe aspectele legate de Laravel și mai puțin pe chestiile generale pe care le puteți citi despre multe alte locuri.
Când descriem comportamentul, care este, de asemenea, cunoscut sub numele de povestiri și specificații, vom folosi o abordare externă. Aceasta înseamnă că de fiecare dată când construim o nouă caracteristică, vom începe prin a scrie povestea utilizatorului general. Acest lucru este în mod normal din perspectiva clienților sau a părților interesate.
Ce asteptam sa se intample atunci cand facem asta?
Nu avem voie să scriem niciun cod până nu avem un pas roșu, de exemplu, dacă nu refăcut codul existent.
Uneori, va fi necesar să rezolvăm iterativ o mică parte a unei povestiri sau a unei trăsături (două cuvinte pe care le folosesc interschimbabil) pe care lucrăm. Acest lucru va însemna adesea scrierea de specificații cu PhpSpec. Uneori vor trece mai multe iterații pe un nivel de integrare sau unitate înainte ca întreaga poveste (la un nivel de acceptare) să treacă. Toate astea sunt foarte complicate, dar într-adevăr nu. Sunt un mare credincios în ceea ce privește învățarea prin practică, deci cred că totul va avea mai mult sens atunci când vom începe să scriem un cod real.
Vom scrie povestiri și specificații pe patru niveluri diferite:
De cele mai multe ori, suita noastra functionala va servi drept stratul nostru de acceptare. Modul în care vom descrie caracteristicile noastre în suita noastră funcțională va fi foarte asemănător cu modul în care vom scrie povestiri de acceptare (folosind un cadru de browser automat) și ar crea o multiplicare de duplicare.
Atâta timp cât povestirile descriu comportamentul din punctul de vedere al clientului, ele servesc ca povești de acceptare. Vom folosi Symfony DomCrawler pentru a testa rezultatul aplicației noastre. Mai târziu, în serie, s-ar putea să constatăm că trebuie să testați printr-un browser real care poate rula și JavaScript. Testarea prin browser adaugă unele preocupări noi, deoarece trebuie să ne asigurăm că vom încărca mediul de testare pe oră atunci când se execută suita.
În suita noastră funcțională, vom avea acces la aplicația Laravel, care este foarte convenabilă. În primul rând, este ușor să se facă diferența între medii. În al doilea rând, nu trece printr-un browser face suita de testare mult mai rapidă. Ori de câte ori vrem să implementăm o nouă caracteristică, vom scrie o poveste în suita noastră funcțională folosind Behat.
Suita noastră de integrare va testa comportamentul părții principale a aplicației noastre, care nu trebuie să aibă acces la Laravel. Suita de integrare va fi, în mod normal, un amestec de povestiri Behat și specificații PhpSpec.
Testele noastre de unitate vor fi scrise în PhpSpec și vor testa unitățile izolate mici ale nucleului aplicației. Entitățile noastre, obiectele valorice etc. vor avea toate specificațiile.
De-a lungul acestei serii, pornind de la următorul articol, vom construi un sistem de urmărire a timpului. Vom începe prin a descrie comportamentul din exterior scriind funcții Behat. Comportamentul intern al aplicației noastre va fi descris folosind PhpSpec.
Împreună, aceste două instrumente ne vor ajuta să ne simțim confortabil cu calitatea aplicației pe care o construim. Vom scrie în primul rând caracteristici și specificații pe trei nivele:
În suita noastră funcțională, vom accesa cu crawlere răspunsurile HTTP ale aplicației noastre într-un mod fără cap, ceea ce înseamnă că nu vom trece prin browser. Acest lucru va facilita interacțiunea cu Laravel și va face ca suita noastră funcțională să servească drept strat de acceptare.
Mai târziu, dacă vom ajunge la un UI mai complicat și ar putea fi necesar să testați și un JavaScript, putem adăuga o suită dedicată acceptării. Această serie este în curs de desfășurare, deci nu ezitați să renunțați la sugestii în secțiunea de comentarii.
Rețineți că pentru acest tutorial, presupun că aveți o instalare proaspătă a lui Laravel (4.2). De preferință folosiți și Laravel Homestead, ceea ce am folosit atunci când am scris acest cod.
Înainte de a începe o lucrare reală, asigurați-vă că avem Behat și PhpSpec în funcțiune. În primul rând, îmi place să fac puțină curățare ori de câte ori încep un nou proiect laravel și să șterg lucrurile de care nu am nevoie:
git rm -r app / teste / phpunit.xml CONTRIBUTING.md
Dacă ștergeți aceste fișiere, asigurați-vă că vă actualizați composer.json
dosar în consecință:
"autoload": "classmap": "app / commands", "app / controllers", "app / models", "app / database / migrations",
Și, desigur:
$ compunere dump-autoload
Acum suntem gata să atragem instrumentele BDD de care avem nevoie. Doar adăugați a necesită-dev
secțiune pentru dvs. composer.json
:
"necesită": "laravel / framework": "4.2. *", "require-dev": "behat / behat": "~ 3.0", "phpspec / phpunit ":" ~ 4.1 ",
"De ce tragem PHPUnit?" s-ar putea sa te gandesti? Nu vom scrie cazuri bune de testare PHPUnit în această serie, dar afirmațiile sunt un instrument la îndemână împreună cu Behat. Vom vedea mai târziu în acest articol când vom scrie prima noastră trăsătură.
Nu uitați să vă actualizați dependențele după modificare composer.json
:
Actualizare compozitor $ --dev
Aproape am terminat de instalat și de configurat lucruri. PhpSpec funcționează din cutie:
$ vendor / bin / phpspec execută 0 specificații 0 exemple 0ms
Dar Behat trebuie să facă o alergare rapidă cu --init
pentru a seta totul:
$ vendor / bin / behat --init + d caracteristici - plasați aici fișierele * .feature aici + d features / bootstrap - plasați aici clasele de context aici + f caracteristici / bootstrap / FeatureContext.php - plasați definițiile, transformările și cârligele aici $ vendor / bin / behat Nu există scenarii Nu există pași 0m0.14s (12.18Mb)
Prima comandă a creat un nou strălucitor FeatureContext
clasa, unde putem scrie definițiile pasului necesare pentru funcțiile noastre:
Scriind prima noastră funcție
Prima noastra facilitate va fi foarte simpla: pur si simplu va asiguram ca noua noastra instalare Laravel ne saluta cu un "Ati ajuns". pe pagina de pornire. Am pus o prostie
Dat
pas,Dat fiind că sunt conectat
, care serveste doar pentru a arata cat de usor interactioneaza cu Laravel in caracteristicile noastre este.Din punct de vedere tehnic, aș clasifica acest tip de caracteristică ca test funcțional, deoarece interacționează cu cadrul, dar servește și ca test de acceptare, deoarece nu vom vedea rezultate diferite de la efectuarea unui test similar printr-un instrument de testare a browserului. Deocamdată vom rămâne cu suita noastră de testare funcțională.
Mergeți și creați o
welcome.feature
fișier și puneți-l înăuntruCaracteristici / funcționale
:# features / feature / welcome.feature Caracteristică: Dezvoltator de bun venit Ca dezvoltator Laravel Pentru a începe un nou proiect, trebuie să fiu întâmpinat la sosire Scenariu: Dezvoltator de felicitări pe pagina de pornire Dat fiind că sunt logat Când vizitez "/" ar trebui să vadă "Ați ajuns."Prin punerea funcțiilor funcționale într-o
funcţional
va fi mai ușor pentru noi să ne gestionăm mai târziu apartamentele. Nu vrem caracteristici de tip de integrare care să nu impună Laravel să aștepte suita funcțională lentă.Îmi place să păstrez lucrurile frumos și curat, așa că cred că ar trebui să avem un context dedicat caracteristic pentru suita noastră funcțională care ne poate oferi acces la Laravel. Puteți să mergeți mai departe și să copiați existența
FeatureContext
fișier și modificați numele clasei laLaravelFeatureContext
. Pentru ca acest lucru să funcționeze, avem nevoie și de obehat.yml
Fișier de configurare.Creați unul în directorul rădăcină al proiectului dvs. și adăugați următoarele:
implicit: suite: funcționale: căi: [% paths.base% / features / functional] contexte: [LaravelFeatureContext]Cred că YAML-ul este destul de explicativ. Suita noastră funcțională va căuta caracteristici în
funcţional
director și să le executați prinLaravelFeatureContext
.Dacă încercăm să vedem Behat în acest moment, ne va spune să implementăm definițiile pasului necesar. Putem avea Behat să adauge metodele goale de schelă la
LaravelFeatureContext
cu următoarea comandă:$ vendor / bin / behat - dry-run --append-snippets $ vendor / bin / behat Caracteristică: Dezvoltator de bun venit ca dezvoltator Laravel Pentru a începe un nou proiect trebuie să fiu întâmpinat în scenariul arival: Pagina principală # Funcții / Funcționare / Bun venit.feature: 6 Având în vedere că sunt logat # LaravelFeatureContext :: iAmLoggedIn () TODO: scrie definiția în așteptare Când văd "/" # LaravelFeatureContext :: iVisit () Apoi ar trebui să văd " " # LaravelFeatureContext :: iShouldSee () 1 scenariu (1 în așteptare) 3 pași (1 în așteptare, 2 omis) 0m0.28s (12.53Mb)Și acum, după cum puteți vedea din ieșire, suntem gata să începem să punem în aplicare primul pas:
Dat fiind că sunt conectat
.Cazul de testare PHPUnit pe care îl livrează cu Laravel ne permite să facem lucruri de genul
$ This-> fi (utilizator $)
, care se înregistrează într-un anumit utilizator. În cele din urmă, dorim să fim capabili să interacționăm cu Laravel ca și cum l-am folosi pe PHPUnit, așa că hai să mergem mai departe și să scriem codul definit de pas "ne-am dori să avem":/ ** * @Deoarece sunt logat * / funcția publică iAmLoggedIn () $ user = new User; $ This-> fi (utilizator $);Acest lucru nu va funcționa bineînțeles, deoarece Behat nu are nicio idee despre lucrurile specifice lui Laravel, dar vă voi arăta într-o clipă cât de ușor este să-i dați pe Behat și Laravel să joace frumos împreună.
Dacă aruncați o privire în sursa Laravel și găsiți
Illuminate \ Fundația \ Testarea \ testcase
clasa, care este clasa la care se prelungește cazul de testare implicit, veți vedea că începând cu Laravel 4.2, totul a fost mutat într-o trăsătură.ApplicationTrait
este acum responsabil pentru bootareacerere
exemplu, configurarea unui client HTTP și oferirea unor metode de ajutor, cum ar fifi()
.Acest lucru este destul de rece, în primul rând pentru că înseamnă că îl putem trage doar în contextele noastre Behat cu aproape nici o configurare necesară. De asemenea, avem acces la
AssertionsTrait
, dar acest lucru este încă legat de PHPUnit.Când tragem trăsătura, trebuie să facem două lucruri. Trebuie să avem a
înființat()
metoda, ca cea dinIlluminate \ Fundația \ Testarea \ testcase
clasa, și avem nevoie de ocreateApplication ()
, precum cea din cazul testului Laravel implicit. De fapt, putem copia aceste două metode și le putem folosi direct.Există doar un singur lucru de observat: în PHPUnit, metoda
înființat()
va fi apelat automat înainte de fiecare încercare. Pentru a obține același lucru în Behat, putem folosi@BeforeScenario
adnotare.Adăugați următoarele la dvs.
LaravelFeatureContext
:utilizați Iluminare \ Fundație \ Testare \ ApplicationTrait; / ** * Clasa de context Behat. * / class LaravelFeatureContext implementează SnippetAcceptingContext / ** * Responsabil pentru furnizarea unei instanțe a aplicației Laravel. * / utilizați ApplicationTrait; / ** * Inițializează contextul. * * Fiecare scenariu devine propriul obiect context. * Puteți, de asemenea, să transmiteți argumente arbitrare constructorului de context prin behat.yml. * / funcția publică __construct () / ** * @BeforeScenario * / funcția publică setUp () if (! $ this-> app) $ this-> refreshApplication (); / ** * Creează aplicația. * * @return \ Symfony \ Component \ HttpKernel \ HttpKernelInterface * / funcția publică createApplication () $ unitTesting = true; $ testEnvironment = 'testarea'; returul necesită __DIR __. '/ ... / ... /bootstrap/start.php';Destul de ușor și să vedem ce avem când conducem Behat:
$ vendor / bin / behat Caracteristică: Dezvoltator de bun venit ca dezvoltator Laravel Pentru a începe un nou proiect, trebuie să fiu întâmpinat pe scenariul arival: Dezvoltator de felicitări pe pagina de pornire # features / functional / welcome.feature: 6 Având în vedere că sunt logat # LaravelFeatureContext :: iAmLoggedIn () Când vizitez "/" # LaravelFeatureContext :: iVisit () TODO: scrie definiție în așteptare Atunci ar trebui să văd "Ați ajuns." # LaravelFeatureContext :: iShouldSee () 1 scenariu (1 în așteptare) 3 pași (1 trecut, 1 în așteptare, 1 omis) 0m0.73s (17.92Mb)Primul pas verde, ceea ce înseamnă că configurația noastră funcționează!
În continuare, putem implementa
Când vizitez
Etapa. Aceasta este foarte ușoară și putem folosi pur și simpluapel()
metodă căApplicationTrait
prevede. O linie de cod ne va duce acolo:/ ** * @ Când vizitez: uri * / funcția publică iVisit ($ uri) $ this-> apel ('GET', $ uri);Ultimul pas,
Atunci ar trebui să văd
, ia ceva mai mult și trebuie să tragem în două dependențe. Vom avea nevoie de PHPUnit pentru afirmație și vom avea nevoie de Symfony DomCrawler pentru a căuta "Ați ajuns." text.Putem implementa astfel:
utilizați PHPUnit_Framework_Assert ca PHPUnit; Folosiți Symfony \ Component \ DomCrawler \ Crawler; ... / ** * @Apoi ar trebui să văd: text * / funcția publică iShouldSee ($ text) $ crawler = Crawler ($ this-> client-> getResponse ()); PHPUnit :: assertCount (1, $ crawler-> filterXpath ("// text () [. = '$ Text']"));Acesta este aproape același cod ca și cum ați scrie dacă utilizați PHPUnit.
filterXpath ()
partea este puțin confuză și nu ne vom îngrijora acum, deoarece este puțin din sfera de aplicare a acestui articol. Doar credeți-mă că funcționează.Rularea Behat o ultimă oară este o veste bună:
$ vendor / bin / behat Caracteristică: Dezvoltator de bun venit ca dezvoltator Laravel Pentru a începe un nou proiect, trebuie să fiu întâmpinat pe scenariul arival: Dezvoltator de felicitări pe pagina de pornire # features / functional / welcome.feature: 6 Având în vedere că sunt logat # LaravelFeatureContext :: iAmLoggedIn () Când vizitez "/" # LaravelFeatureContext :: iVisit () Atunci ar trebui să văd "Ați ajuns." # LaravelFeatureContext :: iShouldSee () 1 scenariu (1 trecut) 3 pași (3 trecuți) 0m0.82s (19.46Mb)Caracteristica funcționează conform așteptărilor și dezvoltatorul este întâmpinat la sosire.
Concluzie
Complet
LaravelFeatureContext
ar trebui să pară asemănătoare cu aceasta:app) $ această-> refreshApplicație (); / ** * Creează aplicația. * * @return \ Symfony \ Component \ HttpKernel \ HttpKernelInterface * / funcția publică createApplication () $ unitTesting = true; $ testEnvironment = 'testarea'; returul necesită __DIR __. '/ ... / ... /bootstrap/start.php'; / ** * @Din care sunt logat * / funcția publică iAmLoggedIn () $ user = new User; $ This-> fi (utilizator $); / ** * @ Când vizitez: uri * / funcția publică iVisit ($ uri) $ this-> apel ('GET', $ uri); / ** * @Apoi să văd: text * / funcția publică iShouldSee ($ text) $ crawler = Crawler nou ($ this-> client-> getResponse () -> getContent ()); PHPUnit :: assertCount (1, $ crawler-> filterXpath ("// text () [. = '$ Text']"));Acum avem o fundație foarte bună pentru a ne dezvolta pe măsură ce continuăm dezvoltarea noii noastre aplicații Laravel utilizând BDD. Sper că ți-am dovedit cât de ușor este să-l ajuți pe Laravel și pe Behat să joace frumos împreună.
Am atins o mulțime de subiecte în acest prim articol. Nu trebuie să vă faceți griji, vom examina mai profund totul, pe măsură ce seria continuă. Dacă aveți întrebări sau sugestii, lăsați un comentariu.