Testarea Dahlem mai ușor cu bătaie de joc

Adevărul amar este că, deși principiul de bază de testare este destul de simplu, dar poate fi destul de o sarcină dificilă - să-l folosească în procesul lor de lucru în fiecare zi. Un astfel jargonul variat, agravând și mai mult toate! Din fericire, există multe instrumente care pot simplifica procesul de testare. Bătaie de joc, cadrul principal pentru crearea de obiecte simulate în PHP, este unul dintre aceste instrumente!

În acest articol, vom considera că, la toate de la sine reprezinta mock obiecte, acestea pot fi utile și de modul în care să pună în aplicare batjocorirea în procesul de testare.

Cercetat cu mock obiecte

Mock-obiect este nimic mai mult decât doar un test de jargon ceea ce înseamnă că simularea comportamentului obiectelor reale. Pur și simplu pune, de multe ori în timpul testării, noi nu vrem să efectueze o anumită metodă. În schimb, trebuie doar să ne asigurăm că metoda a fost invocată.

Luați în considerare următorul exemplu. Imaginați-vă că codul nostru trage o metodă care este conectat la un fișier. În timpul testării acestei logici, probabil că nu doriți să atingă fizic sistemul de fișiere. Din moment ce poate încetini semnificativ viteza testelor tale. În astfel de situații, cel mai bine este de a face o bate joc de clasa ta de a lucra cu sistemul de fișiere, și în loc de a trebui să citească manual fișierul și asigurați-vă că acesta a fost actualizat, pur și simplu verificați că metoda corectă în această clasă se numește. Aceasta este crearea de obiect bate joc! Acest termen nu este nimic în sine nu conține. Doar simulat comportamentul altor obiecte.

Amintiți-vă jargon - este doar jargon. Odată ce nu lasa terminologia confuz te bat din calea de a învăța noi competențe.

Mai ales cu dezvoltarea procesului de proiectare - inclusiv atunci când începe să se aplice principiul responsabilității unic și folosi dependența de injecție - familiarizarea cu mostră obiectul va deveni rapid indispensabil.

Batjocorește vs. Ciorne. cel mai probabil veți fi mult mai probabil să îndeplinească condițiile, cum ar fi bate joc și pintenul. de multe ori unele cu altele, acestea vor fi înlocuite. De fapt, ambele dintre ele sunt folosite pentru scopuri diferite. Prima se referă la procesul de determinare mai lungă așteptare și de verificare a comportamentului necesar. Cu alte cuvinte, mock-obiect poate duce la un test de cădere. Pe de altă parte obiect stub - este doar un set de date sub forma unui ciot, care poate trece pur și simplu, să îndeplinească anumite cerințe.

biblioteca de testare standard de facto pentru PHP - PHPUnit vine cu propriile sale API pentru a crea o machetă de obiecte, care, cu toate acestea, poate fi destul de dificil de utilizat. După cum probabil că aveți timp să vă asigurați că atât mai greu va fi testat, cu atât mai probabil că dezvoltatorul pur și simplu nu va face.

Din fericire, există un număr mare de soluții terțe disponibile prin intermediul Packagist (depozit de pachete pentru compozitor), care va îmbunătăți lizibilitatea testelor, precum și pentru a simplifica scrierea lor în sine. Și, probabil, cel mai important dintre aceste decizii este batjocorirea cadru de bibliotecă pentru crearea mock obiecte.

Biblioteca a fost creată ca o alternativă pentru cei care sunt obosit de sintaxa prea supraîncărcată de PHPUnit, și este un foarte simplu, dar puternic. După cum veți descoperi în curând, biblioteca a devenit un standard în industria de dezvoltare moderne în PHP.

Testarea Dahlem mai ușor cu bătaie de joc

La fel ca multe alte instrumente moderne PHP, batjocorirea pot fi instalate prin intermediul Composer.

La fel ca cele mai multe instrumente PHP in aceste zile este recomandat pentru a instala biblioteca batjocorirea prin compozitor.

Deci, hei, ce altceva pentru compozitor. În prezent, este de preferat în managerul de dependență comunității PHP. Acesta oferă o metodă simplă de determinare a dependențelor de proiect, precum și capacitatea de a le seta cu o singură comandă. Ca modernă PHP-dezvoltator, este important să aveți o înțelegere de bază a compozitorului este și cum să-l folosească.

Înainte ca el nu a folosit, pentru a adăuga un nou fișier de formare composer.json într-un proiect de gol și umple-l cu următoarele:

Prima parte definește JSON că dezvoltarea aveți nevoie de bibliotecă batjocorirea. De la un prompt de comandă executați comanda de instalare compozitorul --dev și descărca biblioteca.

Și, ca un compozitor bonus vine cu propriile sale Autoloader. Sau specificați o listă de directoare în classmap și de a efectua compozitor haldei-autoload sau pur și simplu urmați standard PSR-0, și urmăriți doar pe respectarea structurii de directoare. Du-te aici. pentru a afla mai multe. Dacă încă mai trebuie să vă conectați manual un număr infinit de fișiere în fiecare fișier PHP, este probabil ca ai ceva greșit faci.

Cleduya principiu unic de responsabilitate, ceea ce impune ca fiecare clasă a avut doar un singur motiv să se schimbe. trebuie să împartă logica noastră între două clase: unul pentru generarea de conținut relevant, iar celălalt - pentru a scrie în mod fizic datele într-un fișier. Pentru aceasta avem nevoie de clase Generator și fișiere.

Sfat: de ce să nu utilizați file_put_contents chiar în clasa Generator. Bine, dar mai întâi întrebați-vă: „Cum voi testa?“ Există diverse tehnici care permit lucruri supracontrol, dar este o practică bună de a face un înveliș în loc de această funcționalitate, astfel încât să puteți înlocui cu ușurință, de exemplu, prin batjocorirea!

Iată structura de bază (cu o mică parte din pseudo-cod) din Generatorul nostru de clasă.

injecție de dependență

Acest cod folosește ceea ce noi numim o injecție de dependență. Și încă o dată, este doar jargon programatori pentru a insera o dependențe de clasă prin constructor, în loc de hard-codul lor în codul.

De ce este profitabil? Pentru că altfel nu vom putea înlocui fișierul de clasă. Desigur, putem face un plug pentru clasa de fișiere. dar dacă se inițializează codificată în clasa pe care am testat, nu va exista nici o modalitate de a înlocui stub obiect.

Cel mai bun mod de a crea un test ușor Aplicații--l înainte de fiecare apel metoda, întrebați-vă întrebarea „Cum pot obține acest test?“ Deși există metode de testare dependenta zahardkodennyh, dar utilizarea lor este considerată formă proastă. În schimb, este întotdeauna mai bine pentru a încorpora în funcție de constructor sau prin intermediul setter.

Injecție cârmuitori prin mai mult sau mai puțin identică cu injectarea printr-un constructor. Exact același principiu, singura diferență constă în faptul că relația este construită nu prin metoda constructor, și un setter:

Acum, în cazul în care obiectul de clasă de fișiere va fi trecut la constructor, iar apoi acesta va fi utilizat în clasă. Pe de altă parte, în cazul în care nimic nu a fost transferat, clasa Generatorul se inițializează clasa pe care o doriți. Acest lucru vă permite să facă astfel de variante, cum ar fi:

Vom continua, și în sensul prezentului articol, vom face nimic clasa de fișiere mai mult decât un simplu înveliș de file_put_contents funcția PHP.

Nu este simplu? Să scrie un test pentru a vedea ce problema a fost.

Rețineți că aceste exemple, se presupune că clasele necesare sunt încărcate automat folosind Composer. În fișierul, puteți specifica în mod opțional autoload obiect composer.json. în care puteți declara orice director sau clase pe care doriți să descărcați în mod automat. Nu mai voluminos necesită expresii!

Rula acum PHPUnit. care va reveni următoarele:

Green. Acest lucru înseamnă că putem trece la următoarea sarcină, nu? Ei bine, nu destul. Cu toate că, în realitate, codul sus și de funcționare, dar de fiecare dată când executați testele noastre, sistemul de fișiere va crea un fișier foo.txt. Și ce se întâmplă când ai zeci de teste? Este ușor de imaginat că viteza foarte rapid de testele vor avea de suferit.

Testarea Dahlem mai ușor cu bătaie de joc

Deși testele și au avut succes, dar ele sunt afectate de sistemul de fișiere.

Sper că secțiunea anterioară a dat o explicație exhaustivă de ce aveți nevoie pentru a bate joc de obiecte. Așa cum am menționat anterior, cu toate că putem folosi API-ul nativ al lui PHPUnit, dar nu este cel mai convenabil de a folosi. Pentru a demonstra acest lucru, iată un exemplu de a verifica dacă machetă obiect primește o metodă de apel getName și returnează un John Doe.

Acum, adăugați o condiție de verificare, că metoda getName va fi numit doar o singură dată și de a reveni la John Doe - punerea în aplicare a PHPUnit pare prea greoaie. Cu batjocorirea putem îmbunătăți considerabil lizibilitatea.

Observați cum exemplul anterior este acum mult mai ușor de citit.

Continuând exemplul din secțiunea anterioară, „Dilema“, de data aceasta în clasa GeneratorTest. să facem un obiect bate joc și simula comportamentul clasei fișier folosind biblioteca batjocorirea. Aici este codul actualizat:

Derutează te sun, batjocorirea :: close () în metoda teardown. Acest apel statică șterge batjocorirea container, care este utilizat în testele, și de a efectua toate sarcinile de verificare a declarațiilor dumneavoastră.

Puteți obține o clasă de simulare-obiect folosind metoda batjocorirea :: bate joc (). De obicei, trebuie să specificați atunci ce metode de acest obiect, ne așteptăm ca va fi numit, împreună cu orice argumente necesare. Acest lucru se poate realiza folosind metode shouldReceive (METODA) și cu (ARG).

În acest caz, atunci când ne numim $ generate-> foc (). atunci vom verifica dacă va fi chemat la instanță a metodei puse File. care va fi transferat la calea fișierului și datele de bare foo foo.txt.

Deoarece folosim injecție de dependență, dar acum folosim un plug în loc de un fișier obiect real.

Dacă vom rula din nou testele, acestea vor fi din nou verde, dar clasa de fișiere și, în consecință, sistemul de fișiere în sine nu au fost implicate. Din moment ce nu este nevoie de a apela fisierul clasei. Acesta va fi propriile teste! Zakglushki face pentru a câștiga!

Obiecte simple Mock

Mock-obiecte nu trebuie să se bazeze întotdeauna pe orice clasă. Dacă aveți nevoie doar de un simplu obiect, cum ar fi un utilizator, puteți trece pur și simplu o matrice cu metoda bate joc - în cazul în care va fi creat fiecare pereche cheie-valoare prin mijloace adecvate, care se va returna valoarea corespunzătoare.

Valoarea returnată din Zakomannyh Metode

Este sigur de a fi o situație în care nevoia metodei de clasă zamokannogo pentru a returna o valoare. Continuând exemplul din clasele Generator / fișier că, dacă trebuie să ne asigurăm că, dacă fișierul există deja, acesta nu va fi suprascrise? Cum putem pune în aplicare?

Soluția este de a utiliza metoda în obiect andReturn zamokannogo pentru a simula diferite stări. Iată un exemplu actualizat:

Acest cod actualizat acum controale care există va fi apelată la fișier zamokannogo clasă. și în scopul testului, el va trebui să se întoarcă adevărat. indicând astfel că fișierul există deja și nu ar trebui să fie suprascrise. Apoi vom verifica pentru a vedea că, în astfel de situații acest lucru, metoda de pus în clasa de fișiere nu va fi numit. Bășcălia este ușor de a face cu metoda nu ().

Ar trebui să rulați testele din nou, iar eroarea va fi returnat:

Aha! de testare se așteaptă ca metoda $ this-> File-> există () se numește. dar nu se întâmplă niciodată. Și astfel testul eșuează. Fix asta!

Acest lucru este tot ce trebuie să faci! Cu toate că nu a urmat ciclul de dezvoltare prin testarea (TDD), dar testele noastre peste verde!

Este important să ne amintim că acest stil de testare este eficient, dacă sunteți de testare, de asemenea, în funcție de clasa ta! În caz contrar, în ciuda faptului că testul este verde, în linia de cod server poate rupe. Demonstrația noastră verifică doar că clasa Generator funcționează conform așteptărilor. Nu uita pentru a testa clasa și fișiere!

Pot exista cazuri în care este nevoie de restricții suplimentare. Așa cum este prezentat anterior, acestea pot fi utile în cazurile în care aveți nevoie pentru a verifica dacă a fost cauzată de o metodă specifică cu argumentele necesare. Este important să ne amintim cine așteptați va fi adevărat, în cazul în care metoda este numit cu aceste argumente.

Iată câteva exemple.

Acest exemplu poate fi extins și mai mult și să facă argumentele dinamice. De exemplu, avem nevoie pentru a verifica dacă șirul a fost trecut la metoda:

Sau argument este necesar să se verifice cu o expresie regulată. Verificați dacă numele fișierului se termină cu .txt.

Ei bine, în ultimul exemplu, permițând utilizarea unei game largi de valori disponibile pentru argumentul folosind anyOf.

În acest exemplu, așteptarea ar fi adevărat numai dacă argumentul trecut la metoda get va avea o valoare log.txt sau cache.txt. În caz contrar, batjocorirea arunca o excepție în timpul executării testelor.

Sfat: Nu uitați că puteți seta întotdeauna un alias pentru batjocorirea. de exemplu, m. pentru a face codul de mai lokanichnym: folosiți batjocorirea ca m; Acum este posibil să se utilizeze o structură lakonchinye: m: bate joc ().

Și, în sfârșit, avem mai multe moduri de a indica faptul că metoda ar trebui să se întoarcă zamokanny. De exemplu, trebuie să returneze o valoare booleană. cu ușurință:

parțială Moki

Pot exista situații în care aveți nevoie pentru a face un plug pentru doar o singură metodă unică, mai degrabă decât întregul site ca un întreg. Să presupunem, în scopul exemplul nostru, metoda din clasa noastră se referă la funcția globală pentru a obține valoarea din configurația fișierului.

Deși există diferite tehnici pentru a face un ciot de funcții la nivel mondial. Dar, totuși, este mai bine să se evite apelarea la această metodă. Este în astfel de momente vin în ajutorul parțial Moki.

Observați cum ne-am dat în paranteze numele metodei pe care doriți zamokat. În cazul în care există mai multe metode, pur și simplu, separați-le prin virgule:

O modalitate alternativă de a folosi mokov parțiale poate afirma zamokannogo obiect implicit atunci când toate metodele se referă la clasa părinte, în timp ce pentru ei nu va fi dat nici o așteptare.

Codul anterior poate fi rescris după cum urmează:

În acest exemplu, toate metodele de Clasa_Mea se vor comporta ca de obicei, cu excepția getOption metodei. fi modificat și va reveni 10.000.

Testarea Dahlem mai ușor cu bătaie de joc

Hamcrest bibliotecă oferă un set suplimentar de teste pentru a stabili așteptări.

După ce ați însușit un API batjocorirea, de aceea este recomandat să înceapă utilizarea Hamcrest bibliotecă, care oferă un set suplimentar de constructe pentru a determina așteptări bune de citire. După cum batjocorirea, acesta poate fi instalat prin intermediul Composer.

Odată instalat, puteți începe să utilizați design mai ușor de citit în testele. Iată câteva exemple, inclusiv variații minore pentru a obține un rezultat.

Observați cum Hamcrest vă permite să înregistrați dvs. de verificare, astfel încât acestea să reflecte cât mai mult posibil la așteptările dumneavoastră. Cu ajutorul funcției este () este doar de zahăr sintactic pentru o mai bună lizibilitate.

Veți descoperi în curând că batjocorirea numărate cu Hamcrest destul de bun. De exemplu, dacă utilizați numai batjocorirea, apoi pentru a înregistra această metodă zamokanny ar trebui să fie numit cu un singur argument de tip șir. se procedează după cum urmează:

Folosind aceeași Hamcrest, batjocorirea structura de tip :: poate fi înlocuit cu StringValue (), după cum urmează:

Hamcrest permite resourceValue -soglashenie pentru compararea tipului de valoare.

O alternativă pentru batjocorirea :: orice () în timp ce verificarea pentru orice argument poate fi orice ().

concluzie

Cel mai mare obstacol pentru batjocorirea, nu este de la sine API.

Și o înțelegere de ce și când să utilizeze Moki în testele.

Clasa de fișiere pe care le-am angajat în interacțiune cu sistemul de fișiere. MysqlDb depozit stochează datele. Clasa E-mail implicat în trimiterea de e-mailuri. Rețineți că nici unul dintre aceste exemple nu folosesc cuvinte și.

Odată ce ați înțeles acest lucru, procesul de testare va fi mult mai ușor. Pentru toate operațiunile, care nu intră sub umbra clasei, ar trebui să utilizați injecție de dependență. La testarea, este important să se concentreze asupra unei singure clase, și zamokat toate dependențele necesare. Nu trebuie să testeze toate dintre ele pentru celelalte clase ar trebui să fie propriile teste!

În timp ce nimic nu se poate permite să utilizați punerea în aplicare nativ de a crea mokov în PHPUnit, dar din anumite motive nu folosim mult mai ușor de citit versiune și ușor de utilizat batjocurii?