A existat o perioadă în care programatorii au fost plătiți de numărul de linii de cod pe care le-au scris. Ei au fost tratați ca mașini producătoare de coduri sursă care lucrau în cabine și, în schimb, au considerat programarea doar un loc de muncă pe care îl fac opt ore pe zi și apoi uită de asta, pentru restul zilei.
Dar vremurile s-au schimbat. Cele mai multe locuri de muncă cubice au dispărut, iar programatorii au început să-și iubească meseria. Odată cu apariția tehnicilor Agile și a mișcării software de meserii, au apărut multe instrumente noi pentru a ajuta programatorul și procesul. TDD devine lent modul de facto de scriere a codului, iar secretele lui SCRUM sau Kanban au fost dezvăluite chiar și programatorilor din cele mai întunecate colțuri ale lumii cabinelor.
Testarea automată și dezvoltarea bazată pe teste (TDD) reprezintă unele dintre tehnicile esențiale pe care Agile le-a furnizat programatorilor noștri. Și un instrument care vine cu aceste metodologii este folosit pentru a produce acoperire cod de testare, care este subiectul acestui articol.
"În domeniul informaticii, acoperirea codului este o măsură folosită pentru a descrie gradul în care codul sursă al unui program este testat de o anumită suită de testare". ~ Wikipedia
Definiția de mai sus, luată din Wikipedia, este una dintre cele mai simple modalități de a descrie ce acoperire de cod înseamnă. Practic, în proiectul dvs. aveți o grămadă de cod de producție, precum și o grămadă de cod de testare. Codul de testare exercită codul de producție, iar acoperirea de testare vă arată cât de mult din codul de producție a fost efectuat de teste.
Informațiile pot fi prezentate în mai multe moduri, de la procente simple la grafică frumoasă sau chiar în evidențierea în timp real în IDE-ul favorit.
Vom folosi PHP ca limbă pentru a exemplifica codul nostru. În plus, vom avea nevoie de PHPUnit și XDebug pentru a testa codul nostru și pentru a aduna datele de acoperire.
Aici este codul sursă pe care îl vom folosi. Puteți găsi, de asemenea, în arhiva atașată.
(str string ($ string)> $ cols) $ lastSpaceIndex = strrpos (substr ($ string, 0, $)) cols) "); dacă $ lastSpaceIndex! == false && substr ($ string, $ cols, 1)! = ") retur substr ($ string, 0, $ lastSpaceIndex) string ($ strings, $ cols), $ cols); else return substr ($ string, 0, $ cols) return $ string;
Codul de mai sus conține o funcție simplă care înfășoară textul într-un număr specificat de caractere, pe linie.
Am scris acest cod folosind Test Driven Development (TDD) și avem o acoperire de cod 100% pentru acesta. Acest lucru înseamnă că, prin rularea testului nostru, exersăm fiecare linie a codului sursă.
requ_once __DIR__. '/ ... / WordWrap.php'; clasa WordWrapTest extinde PHPUnit_Framework_TestCase function testItCanWrap () $ w = new WordWrap (); $ this-> assertEquals (", $ w-> wrap (null, 0)); $ this-> assertEquals (", $ w-> wrap (" $ w-> wrap ('a', 1)); $ this-> assertEquals ("a \ nb", $ w-> nc ", $ w-> wrap ('a bc d', 3)); $ this-> assertEquals (" a \ nbc \ nd ";
O modalitate de a obține date de acoperire este de a rula testele noastre în CLI (interfața liniei de comandă) și de a analiza rezultatele. Pentru acest exemplu, vom presupune un sistem de operare similar cu UNIX (Linux, MacOS, FreeBSD, etc). Utilizatorii de Windows vor trebui să adapteze ușor căile și numele executabile, dar ar trebui să fie destul de asemănătoare.
Să deschidem o consolă și să schimbăm directoarele către dvs. Test
pliant. Atunci fugi PHPUnit
cu opțiunea de a genera date de acoperire ca text simplu.
phpunit -coverage-text =. / cover.txt ./WordWrapTest.php
Acest lucru ar trebui să funcționeze din cutia de pe majoritatea sistemelor dacă XDebug este instalat, dar în unele cazuri, este posibil să întâlniți o eroare legată de fusurile orare.
Avertisment PHP: data (): Nu este sigur să vă bazați pe setările zonei de oră a sistemului. Sunteți * necesar * pentru a utiliza setarea date.timezone sau funcția date_default_timezone_set (). În cazul în care ați utilizat oricare dintre aceste metode și dacă primiți în continuare acest avertisment, cel mai probabil ați introdus greșit codul de identificare al zonei de fus orar. Am selectat fusul orar "UTC" pentru moment, dar vă rugăm să setați data.timezone pentru a selecta fusul orar. în phar: ///usr/share/php/phpunit/phpunit.phar/ PHP_CodeCoverage-1.2.10 / PHP / CodeCoverage / Raport / Text.php pe linia 124
Acest lucru poate fi rezolvat cu ușurință prin specificarea setării sugerate în aplicația dvs. php.ini
fişier. Puteți găsi modalitatea de a specifica fusul orar în această listă. Sunt din România, deci voi folosi următoarea setare:
date.timezone = Europa / București
Acum, dacă alergi PHPUnit
comanda din nou, nu ar trebui să vedeți mesaje de eroare. În schimb, rezultatele testului vor fi afișate.
PHPUnit 3.7.20 de Sebastian Bergmann ... Timp: 0 secunde, Memorie: 5.00Mb OK (2 teste, 7 afirmații)
Datele de acoperire vor fi în fișierul text specificat.
$ cat ./coverage.txt Raport de acoperire a codului 2014-03-02 13:48:11 Rezumat: Clase: 100.00% (1/1) Metode: 100.00% (1/1) Linii: 2.68% (14/522) WordWrap Metode: 100,00% (1/1) Linii: 100,00% (7/7)
Să analizăm puțin acest lucru.
WordWrap
este singura noastră clasă.înfășurați ()
metodă, nimic altceva.WordWrap
. Fiecare secțiune are propriile sale metode și detalii de linie. Pe baza acestor observații, putem concluziona că codul nostru este 100% acoperit de teste. Exact cum ne-am așteptat înainte de analizarea datelor de acoperire.
Doar modificând un parametru simplu pentru PHPUnit, putem genera o ieșire HTML plăcută.
$ mkdir ./coverage $ phpunit --coverage-html ./coverage ./WordWrapTest.php
Dacă vă verificați ./ acoperire
director, veți găsi o mulțime de fișiere acolo. Nu voi lipi lista aici pentru că este destul de extinsă. În schimb, vă voi arăta cum arată într-un browser web.
Acesta este echivalentul secțiunii sumare din versiunea textului de mai sus. Putem mări prin urmărirea link-urilor propuse și pentru a vedea mai multe detalii.
Exemplele anterioare au fost interesante și sunt destul de utile, dacă codul dvs. este construit pe un server la distanță la care aveți acces numai la SHH sau la web. Dar nu ar fi frumos să ai toate aceste informații, să trăiești în IDE-ul tău?
Dacă utilizați PHPStorm, totul se află la o distanță de un singur clic! Selectați pentru a rula testele cu acoperire și toate informațiile se vor afișa pur și simplu, în mod magic.
Informațiile despre acoperire vor fi prezente în IDE, în mai multe moduri și în mai multe locuri:
Cu o unealtă atât de puternică în mâinile dezvoltatorului și sub nasul conducerii, era inevitabil ca unele mituri să pară. După ce programatorii au refuzat să fie plătiți de numărul de linii de cod pe care le scriu sau managerii și-au dat seama cât de ușor este sistemul de joc, unii dintre ei au început să plătească programatorii cu procentul de acoperire a codului. Acoperirea de cod mai mare înseamnă că programatorul a fost mai atent, nu? E un mit. Acoperirea codului nu reprezintă o măsură a cât de bine scrieți codul.
Uneori, programatorii tind să creadă că codul cu acoperire de 100% nu are bug-uri. Un alt mit. Acoperirea cu coduri vă spune doar că ați testat fiecare linie de cod. Este o măsură a numărului de linii exercitate. Nu este o măsură a numărului de linii implementate corect. De exemplu, algoritmi pe jumătate scrise cu doar teste jumătate definite vor avea în continuare o acoperire de 100%. Acest lucru nu înseamnă că algoritmul este terminat sau că funcționează corect.
În cele din urmă, gamingul sistemului este foarte ușor. Desigur, dacă utilizați TDD, aveți în mod natural o valoare de acoperire ridicată. Pe proiecte întregi, 100% este imposibil. Dar pe module sau clase mici, obținerea unei acoperire de 100% este foarte ușoară. Luați, de exemplu, codul sursă și imaginați-vă că nu aveți niciun test. Care ar fi cel mai simplu test pentru a exersa tot codul?
funcția testItCanWrap () $ w = WordWrap nou (); $ this-> assertEquals ("a b \ nc", $ w-> wrap ('a b c', 3)); $ this-> assertEquals ("a \ nbc \ nd", $ w-> wrap ('a bc d', 3));
Asta e. Două afirmații și acoperire completă. Nu asta ne dorim. Acest test este atât de departe de a fi descriptiv și complet, încât este ridicol.
Acoperirea codului este un indicator de stare, nu o unitate pentru a măsura performanța sau corectitudinea.
Acoperirea codului este pentru programatori, nu pentru manageri. Este o modalitate de a observa probleme în codul nostru. O modalitate de a găsi clase vechi, netestate. O modalitate de a găsi căi care nu sunt exercitate de teste care ar putea duce la probleme.
Pe proiectele reale, acoperirea codului va fi întotdeauna sub 100%. Atingerea unei acoperire perfectă nu este posibilă sau, dacă este, este rareori o necesitate. Cu toate acestea, pentru a avea o acoperire de 98%, trebuie să vizați 100%. Având altceva ca ținta dvs. este non-sens.
Aici este acoperirea codului aplicației de configurare StorageOS a Syneto.
Totalul este de aproximativ 35%, dar rezultatele au nevoie de interpretare. Majoritatea modulelor sunt în verde, cu o acoperire de peste 70%. Cu toate acestea, există un singur director, Vmware
, care scade în medie. Este un modul cu multe clase care conțin numai definiții pentru API-ul de comunicare. Nu există niciun motiv pentru a testa aceste clase. Acestea au fost generate automat de codul de încredere. Programatorii vor ști asta și vor ști cum să interpreteze rezultatele. Un manager poate insista să-l testeze, deoarece este un bar roșu și arată suspicios pentru cineva care nu cunoaște detaliile interne ale proiectului. Ar avea sens să o testezi? Deloc! Ar fi un test inutil, care ar lua zeci de sute de secunde de timp de construcție fără nici un avantaj.
Deci aici este locul unde suntem cu codul de acoperire: este un instrument excelent pentru programatori, o sursă de informații pentru a evidenția posibilele probleme, o realitate greșită pentru majoritatea managerilor și un alt instrument pentru a forța și măsura activitățile programatorilor. Ca și în cazul oricărui alt instrument, acesta poate fi folosit corect și folosit cu ușurință.