Bazele testării unitare în PHP folosind PHPUnit. Testarea modulelor în PHP Testarea interogărilor bazei de date

Faceți teste unitare în PHP? Nu sunt sigur că am făcut asta vreodată... ce este?

assertEquals(0, count($stack));

array_push($stivă, "foo"); $this->assertEquals("foo", $stiva);$this->assertEquals(1, count($stack));

$this->assertEquals("foo", array_pop($stiva));

$this->assertEquals(0, count($stack));

) ) ?>

Ca mai mult

Personal, îmi place să-mi testez codul în Netbeans (pentru PHP). cu un simplu clic de mouse (alt+f6) îmi pot testa tot codul. Aceasta înseamnă că nu trebuie să părăsesc IDE-ul, care îmi place foarte mult, și ajută la economisirea timpului la comutarea între sesiuni.

O zi buna tuturor! Astăzi aș vrea să vă vorbesc despre ce este testarea unitară în PHP.

Când scrieți chiar și cele mai simple programe, trebuie să vă opriți periodic și să refactorizați pentru a înțelege dacă programul este scris corect. O refactorizarea codului în PHP Am vorbit deja despre asta într-una dintre publicațiile de pe site, pe care o puteți citi.

În general, desigur, această abordare nu este rea, dar are dezavantaje semnificative. Deci, de exemplu, atunci când scrieți un proiect destul de mare, codul se va înfunda treptat cu funcții de depanare comentate, cum ar fi imprimare sau print_r.În cazul lucrului la propriul proiect, al cărui cod nimeni, sau aproape nimeni, nu îl va citi, va fi, într-o oarecare măsură, justificat.

Cu toate acestea, să ne imaginăm această situație: scrieți site-uri web pentru clienți folosind propriul sistem de gestionare a conținutului. Clienții sunt fericiți, te simți grozav, dar într-o zi îți dai seama că sistemul pe care l-ai dezvoltat nu mai îndeplinește cerințele pentru el, are nevoie de schimbări. Și începi să rescrii o parte a sistemului după alta.

Vine un moment când o nouă clasă, metodă, condiție sau ciclu distruge întregul sistem. Schimbările într-un loc duc la erori în altul. Și acum se cățără deja la nesfârșit, parcă dintr-o cornuță a abundenței și devine clar că acest lucru nu se mai poate. Și totul ar fi mult mai bine dacă mai întâi, printre altele, ar fi scris Teste unitare PHP. Nu degeaba spune Martin Fowler: că ori de câte ori încerci să imprimi ceva imprimare pentru depanare sau refactorizare, este mai bine să-l scrieți ca Test unitar.

Deci, se pare că ne-am familiarizat cu teoria, acum să trecem direct la cod. Aici trebuie făcute noțiuni importante; toate operațiunile sunt efectuate pe un computer care rulează Windows 7 cu instalat PHP 7 versiuni. Mai departe va fi punct cu punct.

2) Mutați fișierul descărcat într-un folder C:\bin. Creați un fișier în același folder phpunit.bat, scrieți următorul conținut în el: @php C:\bin\phpunit-6.3.0.phar %*

Vă rugăm să rețineți că calea C:\bin trebuie definit într-o variabilă de sistem CALE, altfel când încercați să executați comanda în consolă phpunit Veți primi o eroare!

3) Deschideți consola și executați comanda phpunit, iar dacă totul este corect, atunci ajutorul ar trebui să fie afișat în consolă.

Desigur, există și alte moduri Instalări PHPUnit, totuși, mi s-a părut că această metodă este cea mai acceptabilă. Pentru Informații suplimentare Puteți accesa oricând site-ul oficial al proiectului PHPUnit. Deci, instalarea este completă, acum să trecem direct la cod.

// fișierul StackTest.php, aflat în directorul C:/Projects/php/tests
// conectați clasa principală TestCase din spațiul de nume PHPUnit\Framework
utilizați PHPUnit\Framework\TestCase;

// definim clasa testată ca descendentă a clasei TestCase
clasa StackTest extinde TestCase
{
// funcțiile testate sunt publice și încep cu cuvântul test
test de funcție publicăPushAndPop()
{
$stiva = ; // a creat o matrice
// și a verificat instrucțiunea assert pentru a se asigura că numărul de elemente din matrice este zero
$acest->

$this->assertEquals("foo", array_pop($stiva));
$this->assertEquals(0, count($stack));
}
}
?>

Codul este bine comentat, dar voi clarifica câteva puncte. piatra de temelie Testarea unitară este afirmația ( afirmaţie). O aserțiune este presupunerea ta despre valoarea așteptată, sau cu alte cuvinte afirmi că valoarea unei variabile, un element de matrice, rezultatul executării unei metode etc. va fi egal cu o astfel de valoare. În exemplul de mai sus, atunci când tabloul este creat inițial, valoarea așteptată a lungimii sale este 0. Acesta este de fapt cazul în exemplul nostru.

ÎN în acest caz, folosim o singură afirmație assertEquals deși în clasă TestCase biblioteci PHPUnit Sunt câteva zeci de ele, pentru toate ocaziile, ca să spunem așa.

Deci am scris testul, ce urmează? Și apoi trebuie lansat. Pentru a face acest lucru, deschideți consola, accesați folderul cu testul nostru ( Teste unitare PHP se află de obicei într-un folder separat teste) și rulați comanda phpunit, trecându-i directorul curent ca argument (indicat printr-un singur punct).

cd C:/Projects/php/tests && phpunit .

Această comandă va trece automat prin toate teste PHP, care se află în acest catalog. Odată ce execuția este completă, va afișa informații despre câte teste au trecut și, eventual, au eșuat.

Astfel, azi am aflat ce este testarea unitară în PHP că folosirea lui este nu numai utilă, ci și necesară. Și dacă știi PHP rău, sau nu știu deloc, atunci special pentru tine am un curs video excelent, în care, în special, discut subiectul în detaliu Testarea unitară în PHP.

Acest script tutorial în PHP arată cum un test poate fi scris ca o singură matrice de întrebări și răspunsuri. Deoarece pot exista mai multe tipuri de întrebări (alegerea „da” - „nu”, alegerea uneia dintre mai multe opțiuni, introducerea unui număr sau șir ca răspuns), vom avea nevoie nu doar de o matrice, ci matrice de matrice, din care fiecare element va descrie tot ceea ce este necesar pentru afișarea și verificarea următoarei întrebări. Acestea vor fi înregistrări cu următoarele chei:

  • „q” - textul de întrebare afișat;
  • „t” - tipul de întrebare care corespunde etichetei HTML dorite: „checkbox” pentru casetele de selectare „da/nu”, „text” pentru un șir sau număr ca răspuns, „select” - pentru o listă în care trebuie să selectați o valoare dintre mai multe. Implementăm selecția mai mult de o valoare cu elementul „multiselect” pe care l-am inventat, care este un grup de casete de selectare procesate împreună, de fapt, o listă standard "; foreach ($test ca $key=>$val) ( error_check ($val); echo ($counter++). "; comutator ($val["t"]) (caz "checkbox": echo $val [" q"]." "; break; case "text": $len = strlen ($val["a"]); echo $val["q"]." ".$element; ecou" "; break; case "multiselect": $i = explode ("|", $val["i"]); echo $val["q"].": "; foreach ($i ca $număr=>$ item) echo $item."
    "; pauză; ) ecou" "; ) funcția error_check ($q) ( $question_types = matrice ("caseta de selectare", "text", "selectare", "multiselect"); $error = ""; if (!isset($q["q"] ) sau empty($q["q"])) $error="Nu există text de întrebare sau este gol" altfel dacă (!isset($q["t"]) sau empty($q["t "]) ) $error="Tipul de întrebare nu este specificat sau este gol"; else if (!in_array($q["t"],$question_types)) $error="Tipul de întrebare nu este specificat"; else if (!isset( $q[ "a"]) sau empty($q["a"]) și $q["a"]!="0") $error="Nu există text de răspuns sau este gol"; dacă ($q[" t"]=="caseta de selectare" și !($q["a"]=="0" sau $q["a"]=="1")) $error = "Răspunsuri 0 sau 1 sunt permise pentru butonul radio" ; else if ($q["t"]=="selectați" || $q["t"]=="multiselect") (if (!isset($q[" i"]) sau gol($q ["i"])) $error="Nu sunt specificate elemente de listă"; else ($i = explode ("|",$q["i"]); if (count( $i)<2) $error="Нет хотя бы 2 элементов списка вариантов ответа с разделителем |"; foreach ($i as $s) if (strlen($s)<1) { $error = "Вариант ответа короче 1 символа"; break; } else { if ($q["t"]=="select" and !array_key_exists($q["a"],$i)) $error="Ответ не является номером элемента списка"; if ($q["t"]=="multiselect") { $a = explode ("|",$q["a"]); if (count($i)!=count($a)) $error="Число утверждений и ответов не совпадает"; foreach ($a as $s) if ($s!="0" and $s!="1") { $error = "Утверждение не отмечено как верное или неверное"; break; } } } } } } if (!empty($error)) { echo "

    Eroare de test găsită: „.$eroare”.

    Informații de depanare:

    "; print_r ($q); exit; ) ) function strlwr_($s) yuya"; $len = strlen ($d="";<$len; $i++) { $c = substr($s,$i,1); $n = strpos($c,$hi); if ($n!==FALSE) $c = substr ($lo,$n,1); $d .= $c; } return $d; } ?>



    Este o situație familiară: dezvolți o aplicație, rezolvi probleme și, uneori, ai impresia că mergi în cerc. Remediați o eroare și apare imediat alta. Uneori este cel pe care l-ai reparat acum 30 de minute, alteori este unul nou. Depanarea devine foarte dificilă, dar există o cale bună și simplă de ieșire din această situație. Testele unitare nu numai că pot reduce durerea dezvoltării, dar vă pot ajuta și să scrieți cod care este mai ușor de întreținut și mai ușor de schimbat.

    Pentru a înțelege ce este testarea unitară, este necesar să se definească conceptul de „modul”. Modul(sau unitate) este o parte a funcționalității aplicației, rezultatul căruia îl putem verifica (sau testa). Testarea unitară- aceasta este de fapt o verificare a faptului că un anumit modul funcționează exact așa cum era de așteptat După ce ați scris testele o dată, de fiecare dată când faceți modificări la cod, tot ce trebuie să faceți este să rulați testele pentru a verifica dacă totul este corect. În acest fel, veți fi întotdeauna sigur că modificările dvs. nu vor rupe sistemul.

    Mituri despre testarea unitară

    În ciuda tuturor beneficiilor testării unitare, nu toți dezvoltatorii îl folosesc. De ce? Există mai multe răspunsuri la această întrebare, dar nu toate sunt scuze foarte bune. Să ne uităm la motivele comune și să încercăm să ne dăm seama de ce nu sunt justificate.

    Scrierea testelor durează prea mult

    Cel mai frecvent motiv: scrierea testelor durează mult. Desigur, unele medii de dezvoltare vor genera un set de teste simple pentru dvs., dar scrierea de teste de înaltă calitate, non-triviale pentru codul dvs. necesită timp. Este o practică normală să petreceți ceva timp scriind teste unitare, ceea ce vă va economisi mult mai mult timp în timp ce mențineți proiectul. Dacă ați dezvoltat un site web, atunci cu siguranță, atunci când adăugați o nouă funcționalitate, l-ați testat pur și simplu făcând clic pe tot felul de link-uri de pe site. Pur și simplu rularea unui set de teste va fi mult mai rapidă decât testarea manuală a tuturor funcțiilor.

    Nu sunt necesare teste - codul funcționează deja!

    O altă scuză pentru dezvoltatori: aplicația funcționează - nu este nevoie de testare. Ei cunosc aplicația și punctele sale slabe și pot repara tot ce trebuie făcut, uneori în câteva secunde. Dar imaginați-vă că angajați un nou dezvoltator pentru a dezvolta o aplicație care nu are idee cum funcționează codul. Un începător poate face unele schimbări care pot distruge orice. Testele unitare vor ajuta la evitarea unor astfel de situații.

    Și încă un motiv pentru care dezvoltatorilor nu le plac testele - nu sunt interesante. Dezvoltatorii prin natura lor iubesc să rezolve problemele. A scrie cod este ca și cum ai crea ceva din gol, a crea ordine din haos, a crea ceva util. Drept urmare, scrierea testelor devine o sarcină plictisitoare, ceva ce poate fi făcut după munca principală. Iar testarea trece în fundal. Dar uită-te la asta din cealaltă parte: să prinzi niște insecte neplăcute ore în șir nu este nicio distracție.

    Exemplu

    Să începem să exersăm. În exemplele noastre vom folosi biblioteca PHPUnit. Cel mai simplu mod de a instala PHPUnit este să trageți de pe canalul PEAR.

    Pear config-set auto_discover 1 pear install pear.phpunit.de/PHPUnit

    Dacă totul merge bine, vor fi instalate toate instrumentele necesare. Dacă doriți să instalați PHPUnit manual, veți găsi instrucțiuni aici.

    Primul test

    Folosind PHPUnit, veți scrie clase de testare care conțin metode de testare, toate care trebuie să îndeplinească următoarele convenții:

    • În cele mai multe cazuri, veți extinde clasa PHPUnit_Framework_TestCase, care vă va oferi acces la metode încorporate precum setUp() și tearDown() .
    • Numele clasei de testare se formează prin adăugarea cuvântului Test la numele clasei testate. De exemplu, testați clasa RemoteConnect, deci numele testerului este RemoteConnectTest.
    • Numele metodelor de testare ar trebui să înceapă întotdeauna cu „test” (de exemplu, testDoesLikeWaffles()). Metodele trebuie să fie publice. Puteți folosi metode private în testele dvs., dar acestea nu vor fi rulate ca teste prin PHPUnit.
    • Metodele de testare nu acceptă parametri. Ar trebui să scrieți metode de testare cât mai independente și autonome posibil. uneori este incomod, dar vei primi teste mai curate, mai eficiente.

    Să scriem o clasă mică pentru a testa RemoteConnect.php:

    Dacă vrem să testăm funcționalitatea pentru conectarea la un server la distanță, atunci trebuie să scriem un test similar:

    assertTrue($connObj->connectToServer($serverName) !== false);

    ) ) ?>

    Clasa de testare moștenește clasa de bază PHPUnit și, prin urmare, toate funcționalitățile necesare. Primele două metode, setUp și tearDown, sunt exemple ale acestei funcționalități încorporate. Acestea sunt funcții de ajutor care fac parte din fiecare test. Ele sunt executate înainte și, respectiv, după rularea tuturor testelor. Dar acum suntem interesați de metoda testConnectionIsValid. Această metodă creează un obiect de tip RemoteConnect și apelează metoda connectToServer.

    Numim o altă funcție de ajutor assertTrue în testul nostru. Această funcție definește cea mai simplă afirmație: verifică dacă valoarea transmisă este adevărată. Alte funcții de ajutor efectuează verificări pentru proprietățile obiectelor, existența fișierelor, prezența cheilor într-o matrice sau potrivirea unei expresii regulate. În cazul nostru, dorim să ne asigurăm că conexiunea la serverul de la distanță este corectă, adică. este că funcția connectToServer returnează true .

    Executarea testelor

    Testele sunt lansate prin simpla apelare a comenzii phpunit care indică fișierul php cu teste:

    Phpunit /path/to/tests/RemoteConnectTest.php

    PHPUnit rulează toate testele și colectează câteva statistici: dacă testul a fost finalizat cu succes sau nu, numărul de teste și aserțiuni și afișează toate acestea. Exemplu de ieșire:

    PHPUnit 3.4 de Sebastian Bergmann. Timp: 1 secundă Teste: 1, Afirmații: 1, Eșecuri 0

    Pentru fiecare test efectuat, rezultatul va fi afișat: "." dacă testul a fost finalizat cu succes, „F” dacă testul a eșuat, „I” dacă testul nu a putut fi finalizat și „S” dacă testul a fost omis.

    PHPUnit oferă un set de verificări de bază care acoperă majoritatea situațiilor posibile. Desigur, uneori trebuie să scrieți teste complicate care testează funcționalitatea netrivială a aplicației dvs. Dar în cea mai mare parte sunt folosite funcțiile de bază ale PHPUnit:

    AssertTrue / AssertFalse Verificarea valorilor transmise pentru egalitatea adevărat/fals
    AssertEquals Verificarea valorilor trecute pentru egalitate
    AssertGreaterThan Compară două variabile (există și LessThan, GreaterThanOrEqual și LessThanOrEqual)
    AssertContains Variabila transmisă conține valoarea specificată?
    AssertType Verificarea tipului unei variabile
    AssertNull Testarea egalității nule
    AssertFileExists Verificarea existenței fișierului
    AssertRegExp Testarea cu expresia regulată

    De exemplu, există o funcție care returnează un obiect (returnSampleObject) și vrem să ne asigurăm că obiectul returnat este de tipul de care avem nevoie:

    returnSampleObject();

    $this->assertType("remoteConnect", $returnedObject); ) ?>

    Un test - o afirmație

    Ca și în toate domeniile dezvoltării software, există cele mai bune practici în testare. Una dintre ele este „un test, o afirmație”. Această regulă vă va ajuta să scrieți teste mici și ușor de citit. Dar uneori apar gânduri: „Din moment ce verificăm asta aici, vom verifica și altceva în același timp!” De exemplu:

    assertGreaterThan(0,strlen($șir));

    $this->assertContains(“42”,$șir); ) ?>

    TestIsMyString nostru efectuează două teste diferite. Mai întâi, testați pentru un șir gol (lungimea trebuie să fie > 0), apoi testați pentru subșirul „42” conținut în șir. Dar acest test poate eșua atât în ​​primul cât și în al doilea caz, iar mesajul de eroare în ambele cazuri va fi același. Prin urmare, merită să respectați principiul „un test - o declarație”. Dezvoltare bazată pe teste (dezvoltare bazată pe teste) Ar fi rău să vorbim despre testare fără a menționa o tehnică comună de dezvoltare - dezvoltarea bazată pe teste (

    dezvoltare bazată pe teste
    • ). TDD este o tehnică utilizată în dezvoltarea de software. Ideea principală a acestei tehnici este că testele sunt scrise mai întâi și numai după ce testele sunt scrise, este scris codul aplicației care va trece aceste teste.

    Aceasta este prima parte a seriei „PHPUnit pentru începători”. În acest ghid, vă vom explica de ce să vă acoperiți codul cu teste unitare și întreaga putere a instrumentului PHPUnit. La final vom scrie un test simplu folosind PHPUnit.

    Înainte de a ne scufunda în PHPUnit, să înțelegem diferitele tipuri de teste. În funcție de modul în care doriți să le clasificați, PHPUnit aplică toate tipurile de teste de dezvoltare software.

    Să clasificam testele în funcție de nivelul lor de specificitate. Conform Wikipedia. În general, există 4 niveluri de testare recunoscute:

    • Testare unitară: Acest nivel testează cea mai mică unitate de funcționalitate.
    • Din punctul de vedere al unui dezvoltator, sarcina lui este să se asigure că funcția testată face exact ceea ce a fost concepută pentru a face. Astfel, trebuie să fie minim sau complet independent de o altă funcție sau clasă. Trebuie scris în așa fel încât să fie executat în întregime în memorie, adică. nu ar trebui să se conecteze la baza de date, să nu acceseze rețeaua sau să folosească FS etc. Testarea unitară ar trebui să fie cât se poate de simplă.
    • Testarea integrării: Acest nivel „conectează” diferite unități de cod și testează dacă combinațiile lor funcționează corect. Este construit pe baza testării unitare și este capabil să detecteze erori care nu pot fi identificate cu ajutorul testării unitare, deoarece Testarea de integrare verifică dacă clasa A funcționează cu clasa B.
    • Testarea sistemului: este conceput pentru a reproduce funcționarea scenariilor în condiții apropiate de luptă. Aceasta, la rândul său, este construită pe lângă testarea integrării. În timp ce testarea integrării asigură că diferite părți ale sistemului funcționează fără probleme. Testarea sistemului este responsabilă pentru a se asigura că sistemul funcționează așa cum se așteaptă utilizatorul înainte de a-l trimite la nivelul următor.

    Testarea de acceptare: În timp ce testele de mai sus sunt destinate dezvoltatorilor în stadiul de dezvoltare, testarea de acceptare este de fapt efectuată de utilizatorii software-ului. Utilizatorii nu sunt interesați de caracteristicile interne ale software-ului, ei sunt interesați doar de modul în care funcționează software-ul.

    Dacă punem tipuri de test într-o piramidă, ar arăta astfel:

    Ce este PHPUnit

    Aici intervine PHPUnit. În prezent, PHPUnit este cel mai popular cadru de testare unitară din PHP. Pe lângă faptul că are caracteristici precum obiectele batjocoritoare, poate analiza și acoperirea codului, înregistrarea în jurnal și oferă mii de alte caracteristici.

    Să instalăm PHPUnit pe sistemul nostru:

    1. Descărcați-l: PHPUnit este distribuit într-un fișier PHAR(PHp ARhive). Îl poți descărca.
    2. Adăugați calea acestuia la variabila de sistem $PATH: după descărcarea fișierului PHAR, asigurați-vă că este executabil și calea în care se află este înregistrată în variabila de sistem $PATH. Că. îl poți rula de oriunde.

    Dacă lucrați pe un sistem asemănător Unix, atunci puteți face acest lucru cu următoarele comenzi:

    $ wget https://phar.phpunit.de/phpunit.phar $ chmod +x phpunit.phar $ sudo mv phpunit.phar /usr/local/bin/phpunit

    Dacă ați făcut totul corect, puteți vedea versiunea PHPUnit instalată tastând comanda în terminalul dvs.:

    $phpunit --versiune

    Primul tău test unitar

    Este timpul să scrieți primul test unitar! În primul rând, avem nevoie de o clasă pe care o vom testa. Să scriem o clasă simplă numită Calculator. Și să scriem un test pentru el.

    Creați un fișier „Calculator.php” și copiați codul de mai jos în el. Această clasă Calculator are o singură metodă de adăugare.

    Calculator de clasă (funcția publică adaugă($a, $b) ( returnează $a + $b; ) )

    Acum creați un fișier de test „CalculatorTest.php” și copiați următorul cod în el. Vom analiza fiecare metodă mai detaliat.

    Necesită „Calculator.php”; clasa CalculatorTests extinde PHPUnit_Framework_TestCase ( $calculator privat; funcția protejată setUp() ( $this->calculator = new Calculator(); ) protected function tearDown() ( $this->calculator = NULL; ) public function testAdd() ( $rezultat = $this->calculator->add(1, 2) $this->assertEquals(3, $result) );

    • Linia 2: conectați fișierul clasei testate Calculator.php. Deoarece aceasta este clasa pe care o vom testa în acest fișier, asigurați-vă că este inclusă.
    • Linia 8: setUp() este o metodă care este apelată înainte de fiecare test. Ține minte el chemat înainte de fiecare test, ceea ce înseamnă că dacă adăugați o altă metodă de testare la această clasă, aceasta va fi apelată și înaintea acesteia.
    • Linia 13: Similar cu metoda setUp(), tearDown() este apelată după fiecare test.
    • Linia 18: testAdd() este o metodă de testare pentru metoda add(). PHPUnit va recunoaște fiecare metodă care începe cu test ca metodă de testare și o va rula automat. Această metodă este de fapt foarte simplă: mai întâi apelăm metoda Calculator::add() pentru a calcula valoarea 1 plus 2, apoi verificăm că această metodă a returnat valoarea corectă folosind assertEquals() din PHPUnit.

    Partea finală a muncii efectuate este să rulați PHPUnit și să verificați dacă toate testele trec (rulați fără erori). În terminalul dvs., mergeți la directorul în care ați creat fișierul de testare și rulați următoarea comandă:

    $phpunit CalculatorTest.php

    Dacă ați făcut totul corect, ar trebui să vedeți ceva de genul acesta:

    PHPUnit 3.7.32 de Sebastian Bergmann. . Timp: 31 ms, memorie: 2,25 Mb OK (1 test, 1 afirmație)

    Concluzie

    Am finalizat primul tutorial din seria „PHPUnit pentru începători”. În următorul articol vă vom arăta cum să utilizați un furnizor de date în teste.

    Sperăm că acest ghid simplu vă va ajuta în dezvoltarea dvs. și vă va ajuta să începeți să utilizați testarea unitară.

    Dacă ți-a plăcut traducerea pe acest subiect, citește-ne la



Publicații pe această temă