Ghidul începătorului pentru testarea unităților construirea unui plug-in testabil

În prima parte a acestei serii, am analizat metodologiile de testare la nivel înalt și am dat câteva exemple despre motivul pentru care este benefic pentru noi să începem să facem în proiectele noastre WordPress. De asemenea, am făcut timp pentru a configura PHPUnit și testele WordPress pentru a începe construirea primului plugin testabil.

În acest articol final vom defini o metodologie pentru testarea unității, vom începe să o încorporăm în activitatea noastră și vom pleca cu un plugin complet funcțional (deși simplu) care are, de asemenea, un set mic de teste pentru a se asigura că funcționează exact cum era de așteptat.


O metodologie de testare a unităților

Când vine vorba de testare, există în general două moduri de a face acest lucru:

  • Scrieți testele, apoi scrieți codul pentru a trece încercările
  • Scrieți codul, apoi scrieți testele care trec

Din experiența mea, prima abordare este întotdeauna mai bună. Acordat, acest lucru este practic imposibil în contextul unei aplicații deja existente, dar dacă începeți de la început - ceea ce suntem - este o abordare mai bună și de aici: De îndată ce ați scris o aplicație, dvs. știți cum funcționează. Ca atare, poate fi extrem de dificil să scrieți teste care întind aplicația atunci când știți în mod inerent cum ar trebui să funcționeze.

În acest scop, îmi pare mai bine să scriu testele primul. În acest fel, testele dvs. nu includ numai modul în care este programul presupus pentru a lucra, dar devine, de asemenea, o formă de documentație care arată ce funcționalitate este destinată și va duce în cele din urmă la un eșec atunci când funcționalitatea nu funcționează așa cum ar trebui.

Având în vedere acest lucru, vom construi cu această metodologie simplă:

  • Scrieți un test și executați-l. În mod evident, va eșua.
  • Scrieți codul care încearcă să treacă testul.
  • Dacă testul trece, vom trece la următoarea funcție; în caz contrar, repetăm ​​procesul până nu trece.

În cele din urmă, ca o reîmprospătare, plugin-ul nostru va da un mesaj de bun venit specializat vizitatorului pe baza faptului că au accesat site-ul de pe Google sau Twitter. De asemenea, vom scrie acest lucru astfel încât să fie mai ușor să vă extindeți cu servicii suplimentare, dacă doriți să faceți acest lucru în viitor.


Construirea unui Plugin Testabil

În acest moment, este timpul să începeți să scrieți un cod; cu toate acestea, spre deosebire de cele mai multe proiecte, nu vom fi sărituri în codul WordPress specific încă. În schimb, vom elimina clasa de testare a unităților. Dacă ați structurat directorul plugin-ului pe baza a ceea ce am împărțit în prima postare sau cum l-am configurat pe GitHub, atunci ar trebui să aveți o hello_reader_tests.php fișierul din fișierul dvs. teste / wordpress-teste director. Nu trebuie să urmați această organizație, desigur, dar aceasta va ajuta în timp ce progresăm prin proiect.

Să eliminăm clasa de testare a unității:

requ_once ('... / ... /plugin.php'); clasa Hello_Reader_Tests extinde WP_UnitTestCase  // clasa de sfârșit

Acum, încercați să rulați testul folosind terminalul folosind unitatea PHP. Presupunând că rulați unitatea PHP din instalarea locală MAMP, ar trebui să puteți introduce:

$ /Applications/MAMP/bin/php/php5.3.6/bin/phpunit ./hello_reader_tests.php

În acest moment, ar trebui să vedeți un eșec:

Asta e bine! Aceasta înseamnă că PHPUnit este instalat și rulat și că cadrul dvs. de testare WordPress este gata să meargă. Testul a eșuat doar pentru că nu am scris niciun test. Să începem să facem asta.

Primul nostru test

Mai întâi, să scriem un test pentru a ne asigura că pluginul nostru este inițializat, instanțiat și pregătit pentru testare. Reamintim mai devreme în primul articol că am stocat o referință la instanța Hello Reader în PHP $ GLOBALS matrice. Acesta este modul în care vom accesa acel exemplu utilizând cadrul de testare. Deci, să actualizăm testul unitar pentru a arăta astfel:

Rețineți că, din motive de spațiu, voi renunța la comentariile de cod, dar plugin-ul complet testat și testele vor fi disponibile pe GitHub.

requ_once ('... / ... /plugin.php'); clasa Hello_Reader_Tests extinde WP_UnitTestCase private $ plugin; funcția setUp () părinte :: setUp (); $ this-> plugin = $ GLOBALS ['salut-cititor'];  // funcția de configurare finală testPluginInitialization () $ this-> assertFalse (null == $ this-> plugin);  // end testPluginInitialization // clasa de sfârșit

Mai sus, am setat o referință la instanța plugin-ului, astfel încât să putem accesa el în timpul testelor de unitate. Folosim înființat metoda de a lua referința la pluginul de la $ GLOBALS. Rețineți, totuși, că am introdus o altă funcție numită testPluginInitialization. Această funcție verifică faptul că referința pe care am configurat-o în înființat metoda nu este nulă.

Dacă reluați testele, ar trebui să obțineți un test de trecere și terminalul dvs. ar trebui să arate astfel:

Există o importantă experiență aici: Rețineți că funcția unică pe care am furnizat-o mai sus are un scop clar: să se verifice dacă plugin-ul a fost inițializat corespunzător. Numele funcției sale este clar și conține o singură instrucțiune assert. Aceasta este o modalitate excelentă de a modela testele noastre rămase, în primul rând pentru că ușurează găsirea de erori atunci când apar. Gândiți-vă la acest lucru: dacă includeți o serie de afirmații diferite afirmați într-o singură funcție, va fi dificil să determinați ce afirmație de afirmație nu reușește.

Prima funcție

Acum, când ne-am prezentat cum să scriem teste unitare, să executați teste de unitate și să evaluați modul în care acestea trec sau cum nu reușesc, să începem să implementăm funcționalitatea pluginului. În primul rând, va trebui să configuram un filtru pentru conținut, deoarece vom adăuga text la începutul conținutului. Urmând metodologia pe care am definit-o mai devreme în acest articol, să scriem primul nostru test.

Acest test special va încerca să văd dacă am adăugat un set specific de text în prima parte a postării:

funcția testAddWelcomeMessage () $ this-> assertEquals ('CONTESTUL TESTULUI', $ this-> plugin-> add_welcome_message ('Acesta este un exemplu de postare a mesajului. ) adaugă mesajul de bun venit la conținutul mesajului. ');  / / end testAddWelcomeMessage

Dacă executați testul exact așa cum este acesta, acesta nu va eșua - în schimb, PHPUnit va întoarce o eroare fatală deoarece metoda nu este definită în plugin. Deci, să adăugăm asta acum. Actualizați pluginul pentru a arăta astfel:

clasa Hello_Reader function __construct () add_filter ('the_content', array (& $ this, 'add_welcome_message'));  // funcția publică a constructorului final add_welcome_message ($ content)  // end add_welcome_message // clasa de sfârșit

Acum încercați să executați testul. Testul nu va bombarda, dar ar trebui să vedeți un eșec împreună cu un mesaj clar despre motivul pentru care testul a eșuat:

1) Hello_Reader_Tests :: testAddWelcomeMessage add_welcome_message () adaugă mesajul de întâmpinare la conținutul mesajului. Nu a reușit să se afirme că se așteaptă meciuri nulă "TEST CONTENT"

Deci, în conformitate cu metodologia noastră, vrem să facem acest test. Pentru a face acest lucru, trebuie să vă asigurați că conținutul mesajului conține șirul de text - în acest caz, "CONȚINUTUL TESTULUI", pentru a face trecerea. Așa că hai să încercăm asta. Actualizați funcția corespunzătoare din plugin pentru a adăuga șirul înainte de conținut:

funcția publică add_welcome_message ($ content) returnează 'CONTESTUL TESTULUI'. conținut de $;  // end add_welcome_message

Și din nou, reluăm testul numai pentru a vedea că acesta nu reușește. Dacă observați testul nostru, acest lucru se datorează faptului că încearcă să vadă conținutul nostru este egală ''CONȚINUTUL TESTULUI"șir. În schimb, trebuie să ne asigurăm că șirul începe cu conținutul. Aceasta înseamnă că trebuie să ne actualizăm testul. Din fericire, PHPUnit are o funcție assertContains. Deci, să actualizăm codul nostru pentru al folosi:

funcția testAddWelcomeMessage () $ this-> assertContains ('CONTENTUL TESTULUI', $ this-> plugin-> add_welcome_message ('Acesta este un exemplu de postare a mesajului. ) adaugă mesajul de bun venit la conținutul mesajului. ');  / / end testAddWelcomeMessage

Încă o dată, reluați testul și ar trebui să vedeți că testul trece acum. Minunat! Acum trebuie să scriem mesaje personalizate pentru persoanele care vin de pe Twitter și persoanele care vin de la Google.

Primirea vizitatorilor Twitter

Există o serie de moduri diferite pe care le putem verifica pentru a vedea cum a ajuns un utilizator la o anumită pagină. Uneori putem verifica valorile din $ _GET array, uneori putem interoga $ _SERVER array sau, uneori, putem verifica sesiunea unui utilizator. Pentru scopurile acestui exemplu, vom căuta "twitter.com" care să fie găsit în $ _SERVER [ 'HTTP_REQUEST']. Spun asta doar ca voi să puteți urmări împreună cu ceea ce facem în cod.

Deci, în general vorbind, add_welcome_message ar trebui să verificați dacă cererea a venit de pe Twitter și apoi să ajustați mesajul în mod corespunzător. Deoarece suntem în faza de testare a fiecărei bucăți de funcționalitate, putem scrie o funcție care să poată evalua dacă cererea vine de pe Twitter. Deci, să scriem un nou test:

În plugin:

funcția publică is_from_twitter ()  // end is_from_twitter

În test:

funcția testIsComingFromTwitter () $ _SERVER ['HTTP_REFERER'] = 'http://twitter.com'; $ this-> assertTrue ($ this-> plugin-> is_from_twitter (), 'is_from_twitter () se va întoarce în momentul în care site-ul referitor este Twitter.');  // end testIsComingFromTwitter

Evident, suntem falsificați HTTP_REFERER valoare, dar acest lucru este bine pentru scopurile acestui exemplu. Punctul rămâne: conduceți testul, acesta va eșua și astfel va trebui să implementăm funcția din plugin pentru a avea succes:

funcția publică is_from_twitter () retur strpos ($ _SERVER ['HTTP_REFERER'], 'twitter.com')> 0;  // end is_from_twitter

Reanalizarea testului ar trebui să conducă acum la un test de deplasare. Dar așteptați - trebuie să fim complet. Să ne asigurăm că executăm un test pentru a verifica dacă această funcție nu reușește atunci când este recomandată nu de la Twitter.

function testIsNotComingFromTwitter () // Spoofing HTTP_REFERER pentru scopurile acestui test si postul de blog insotitor $ _SERVER ['HTTP_REFERER'] = 'http://facebook.com'; $ this-> assertFalse ($ this-> plugin-> is_from_twitter (), 'is_from_twitter () se va întoarce în momentul în care site-ul referitor este Twitter.');  // end testIsNotComingFromTwitter

Observați că l-am actualizat HTTP_REFERER și ne-am schimbat assertTrue la assertFalse. Permițând orice altceva este corect, executați testele și ar trebui să treacă.

Repetarea aceluiași lucru pentru Google

Furnizarea unui mesaj personalizat pentru Google va necesita acelasi lucru pe care l-am facut si pentru Twitter, adica spoof-ul HTTP_REFERER și apoi reveniți la adevărat sau fals pentru funcția de ajutor. Deci, pentru a evita sondarea redundantă, voi păstra această secțiune cât mai concisă posibil. Aceiași pași trebuie urmăriți ca și în cazul Twitterului.

În primul rând, vom elimina funcția de ajutor în plugin:

funcția publică is_from_google ()  // end is_from_google

Apoi testăm testul:

funcția testIsComingFromGoogle () $ _SERVER ['HTTP_REFERER'] = 'http://google.com'; $ this-> assertTrue ($ this-> plugin-> is_from_google (), 'is_from_google () se va întoarce când site-ul referitor la Google este.');  // end testIsComingFromGoogle

Rularea testului așa cum se întâmplă acum va duce la o eșec. Deci, să punem în aplicare is_from_google () funcţie:

funcția publică is_from_google () return strpos ($ _SERVER ['HTTP_REFERER'], 'google.com')> 0;  // end is_from_twitter

Și acum, testul ar trebui să treacă. Dar, din nou, trebuie să fim compleți, așa că să scriem testul de eșec pentru a presupune că funcția nu va reveni adevărată când utilizatorii vin din altă parte:

funcția testIsNotComingFromGoogle () // Spoofing HTTP_REFERER pentru scopurile acestui test și postul de blog însoțitor $ _SERVER ['HTTP_REFERER'] = 'http://facebook.com'; $ this-> assertFalse ($ this-> plugin-> is_from_google (), 'is_from_google () se va întoarce la adevărat atunci când site-ul referitor la Google este.');  // end testIsNotComingFromGoogle

În cele din urmă, executați testele. Permițând orice altceva este corect, ar trebui să aveți șase teste trecute.

Trageți-i pe toți împreună

În acest moment, avem tot ce trebuie să începem să afișăm mesaje personalizate de întâmpinare utilizatorilor noștri. Singurul lucru este că va trebui să refactorăm testul nostru inițial care verifică "CONTENTUL TESTULUI". Acum, va trebui să introducem teste pentru următoarele cazuri:

  • Când utilizatorul vine de pe Twitter, vom spune "Bine ați venit de pe Twitter!"
  • Când utilizatorul vine de la Google, vom spune "Bine ați venit de la Google!"
  • Când utilizatorul vine de oriunde altundeva, nu vom premediza nimic.

Deci, să eliminăm testul pe care l-am creat mai devreme testAddWelcomeMessage în locul adăugării a trei noi teste.

În primul rând, vom adăuga un test care verifică mesajul de întâmpinare Twitter.

În plugin, vom reduce add_welcome_message la acest:

funcția publică add_welcome_message ($ content) return $ content;  // end add_welcome_message

Și vom adăuga testul Twitter, în primul rând:

funcția testDisplayTwitterWelcome () // Spoof HTTP_REFERER pentru Twitter $ _SERVER ['HTTP_REFERER'] = 'http://twitter.com'; $ this-> assertContains ('Bine ati venit de pe Twitter!', $ this-> plugin-> add_welcome_message ('Acesta este un exemplu de postare a mesajului. mesaj către conținutul mesajului. ");  // end testDisplayTwitterWelcome

În acest moment, asta e pălăria veche, nu? Rulați-o, testul va eșua. Implementați add_welcome_message pentru a arata astfel:

funcția publică add_welcome_message ($ content) if ($ this-> is_from_twitter ()) $ content = 'Bine ați venit de pe Twitter!' . conținut de $;  // se închide dacă returnează $ content;  // end add_welcome_message

Rulați din nou, și va trece. Următorul este testul Google:

function testDisplayGoogleWelcome () // Spoof HTTP_REFERER pentru Google $ _SERVER ['HTTP_REFERER'] = 'http://google.com'; $ this-> assertContains ('Bine ati venit de la Google!', $ this-> plugin-> add_welcome_message ('Acesta este un exemplu de postare a mesajului. mesaj către conținutul mesajului. ");  // test finalDisplayGoogleWelcome

Executați testul, nu reușiți, apoi actualizați add_welcome_message în plugin-ul pentru a conține un cec folosind funcția de helper pe care am scris-o mai devreme:

funcția publică add_welcome_message ($ content) if ($ this-> is_from_twitter ()) $ content = 'Bine ați venit de pe Twitter!' . conținut de $;  altfel dacă ($ this-> is_from_google ()) $ content = 'Bine ați venit de la Google!' . conținut de $;  // se închide dacă returnează $ content;  // end add_welcome_message

În acest moment, ar trebui să aveți un plug-in complet funcțional, care are șapte teste unitare!


Concluzie

După cum puteți vedea, testarea unităților introduce un nivel suplimentar de dezvoltare, dar poate fi plătită semnificativ în codul sustenabil, bine organizat și testabil. Pe măsură ce cererea dvs. crește, executați continuu teste pentru a verifica dacă proiectele dvs. funcționează conform așteptărilor. Desigur, acesta este doar un mic exemplu de funcționare a testării unității. Aplicarea acestor practici se poate realiza în proiecte mult mai mari și / sau mai complicate.

În cele din urmă, puteți găsi acest plugin, testele WordPress și testele unității Hello Reader comentate complet pe GitHub.

Cod