Testarea codului dvs. este enervant, dar impactul de a nu face acest lucru poate fi ordine de mărime mai enervant! În acest articol, vom folosi dezvoltarea bazată pe test, pentru a scrie și testa codul nostru mai eficient.
De la începutul erei computerelor, programatorii și bug-urile s-au luptat pentru supremație. Este un eveniment inevitabil. Chiar și cei mai mari programatori cad pradă acestor anomalii. Niciun cod nu este sigur. De aceea facem teste. Programatorii, cel puțin cei sane, își testează codul executându-l pe mașinile de dezvoltare pentru a se asigura că face ceea ce trebuia să facă.
Dezvoltare bazată pe dezvoltare este o tehnică de programare care vă cere să scrieți simultan codul actual și codul de testare automatizat. Acest lucru vă asigură că vă testați codul și vă permite să vă retestați codul rapid și ușor, deoarece este automatizat.
Dezvoltarea bazată pe dezvoltare, sau TDD așa cum o vom numi de acum încolo, se învârte în jurul unui ciclu de dezvoltare iterativ scurt, care merge cam așa:
Ați încercat vreodată să testați un program deoarece:
De cele mai multe ori, nu se întâmplă nimic, și vă mutați cu succes codul la producție fără probleme. Dar uneori, după ce te-ai mutat la producție, totul merge prost. Sunteți blocați fixând o sută de găuri într-o navă scufundată, cu mai multe apariții în fiecare minut. Tu faci nu doriți să vă aflați în această situație.
TDD a fost menită să elimine scuzele noastre. Când un program a fost dezvoltat folosind TDD, ne permite să facem schimbări și să încercăm rapid și eficient. Tot ce trebuie să facem este să executați testele automate și voila! Dacă trece toate testele automate, atunci suntem bine să mergem - dacă nu, atunci înseamnă doar că am rupt ceva cu schimbările. Cunoscând care părți exacte ale testului au eșuat, ne permite, de asemenea, să identificăm cu ușurință ce parte din schimbările s-au rupt, ceea ce face ca fixarea bugurilor să fie mai ușoară.
Există o multitudine de cadre de testare automate PHP pe care le putem folosi. Unul dintre cele mai utilizate cadre de testare este PHPUnit.
PHPUnit este un cadru de testare excelent, care poate fi ușor integrat în propriile proiecte sau alte proiecte construite pe baza cadrelor PHP populare.
Cu toate acestea, pentru scopurile noastre, nu vom avea nevoie de multitudinea de funcții oferite de PHPUnit. În schimb, vom opta pentru a crea testele noastre folosind un cadru de testare mult mai ușor, numit SimpleTest.
În pașii următori, să presupunem că dezvoltăm o aplicație de cărți de oaspeți, în care orice utilizator poate adăuga și vedea intrări din cărțile de vizită. Să presupunem că marcarea a fost terminată și că pur și simplu facem o clasă care conține aplicație logică a cărții de oaspeți, unde aplicația se inserează și citește în baza de date. Partea de lectură a acestei clase este ceea ce vom dezvolta și vom testa.
Acesta este, fără îndoială, cel mai ușor pas al tuturor. Chiar și acest tip ar putea face acest lucru:
Descărcați SimpleTest aici și extrageți-l într-un dosar la alegere - de preferință folderul în care vă veți dezvolta codul sau PHP include_path pentru acces ușor.
Pentru acest tutorial, am creat dosarul ca acesta:
Index.php va rula guestbook.php și va invoca metoda de vizualizare și va afișa înregistrările. În interiorul directorului de clase este locul unde vom pune clasa guestbook.php, iar dosarul de testare este locul unde plasăm cea mai simplă bibliotecă.
Al doilea pas, care este de fapt cel mai important, este de a începe să vă creați testele. Pentru aceasta, trebuie să vă planificați și să vă gândiți la ceea ce va face funcția dvs., ce posibile intrări va obține și rezultatele pe care le va trimite. Acest pas seamănă cu jocul de șah - trebuie să știți totul despre adversar (programul), inclusiv toate slăbiciunile sale (erori posibile) și punctele forte (ce se întâmplă dacă se execută cu succes).
Deci, pentru aplicația noastră de cărți de oaspeți, să lăsăm schemele:
Array (['name'] = "Bob" ['message'] = "Bună ziua, sunt Bob" ['message'] = "Bună, sunt Tom"))
Acum, putem scrie primul nostru test. Să începem prin crearea unui fișier numit guestbook_test.php în dosarul de testare.
Apoi, să convertim ceea ce am stabilit de la pasul doi,.
adaugă ("Bob", "Bună, sunt Bob"); $ guestbook-> add ("Tom", "Bună, sunt Tom"); $ entries = $ guestbook-> viewAll (); $ count_is_greater_than_zero = (număr ($ intrări)> 0); $ This-> assertTrue ($ count_is_greater_than_zero); $ this-> assertIsA ($ intrări, 'array'); foreach ($ intrări ca intrare $) $ this-> assertIsA ($ entry, 'array'); $ This-> assertTrue (isset ($ intrare [ 'nume'])); $ This-> assertTrue (isset ($ intrare [ 'mesaj'])); function testViewGuestbookWithNoEntries () $ guestbook = carte de oaspeți nouă (); $ Guestbook-> deleteAll (); // Ștergeți mai întâi toate intrările astfel încât să știm că este o tabelă goală $ entries = $ guestbook-> viewAll (); $ this-> assertEqual ($ intrări, array ());Aserțiunile vă asigură că un anumit lucru este ceea ce ar trebui să fie - în principiu, se asigură că ceea ce se întoarce este ceea ce așteptați să revină. De exemplu, dacă o funcție ar trebui să se întoarcă la adevărat dacă are succes, atunci în testul nostru ar trebui afirma că valoarea returnată este egală cu cea reală.
După cum puteți vedea aici, testarea vizualizării cărții de oaspeți cu intrări și fără. Verificăm dacă aceste două scenarii ne transmit criteriile noastre de la pasul doi. Probabil că ați observat că fiecare dintre funcțiile noastre de testare începe cu cuvântul "test". Am făcut acest lucru pentru că, atunci când SimpleTest rulează această clasă, va căuta toate funcțiile care încep cu cuvântul "test" și o execută.
În clasa noastră de test, am folosit și câteva metode de afirmație, cum ar fi assertTrue, assertIsA și assertEquals. Funcția assertTrue verifică dacă o valoare este sau nu adevărată. AssertIsA verifică dacă o variabilă este de un anumit tip sau clasă. În cele din urmă, AssertEquals verifică dacă o variabilă este total egală cu o anumită valoare.
Există alte metode de afirmare oferite de SimpleTest, care sunt:
assertTrue ($ x) | Fail dacă $ x este falsă |
assertFalse ($ x) | Fail if $ x este adevărat |
assertNull ($ x) | Fail if $ x este setat |
assertNotNull ($ x) | Fail dacă $ x nu este setat |
assertIsA ($ x, $ t) | Fail if $ x nu este clasa sau tipul $ t |
assertNotA ($ x, $ t) | Fail dacă $ x este de clasă sau tip $ t |
assertEqual ($ x, $ y) | Fail dacă $ x == $ y este falsă |
assertNotEqual ($ x, $ y) | Fail if $ x == $ y este adevărat |
assertWithinMargin ($ x, $ y, $ m) | Fail dacă abs ($ x - $ y) < $m is false |
assertOutsideMargin ($ x, $ y, $ m) | Fail dacă abs ($ x - $ y) < $m is true |
AssertIdentical ($ x, $ y) | Fail dacă $ x == $ y este falsă sau o nepotrivire de tip |
assertNotIdentical ($ x, $ y) | Fail dacă $ x == $ y este adevărată și tipurile se potrivesc |
assertReference ($ x, $ y) | Fail unless $ x și $ y sunt aceeași variabilă |
assertClone ($ x, $ y) | Fail unless $ x și $ y sunt copii identice |
assertPattern ($ p, $ x) | Fail unless regex $ p se potrivește cu $ x |
assertNoPattern ($ p, $ x) | Fail if regex $ p se potrivește cu $ x |
expectError ($ x) | Înghite orice eroare de potrivire viitoare |
afirma ($ e) | Respingerea obiectului de așteptare eșuat $ e |
Modalitatea de afirmare este curtoazie de http://www.simpletest.org/en/unit_test_documentation.html
După ce ați terminat de scris codul, trebuie să executați testul. Prima dată când executați testul, acesta Ar trebui să nu reușească. Dacă nu, înseamnă că testul dvs. nu testează nimic.
Pentru a rula testul, pur și simplu alerga guestbook_test.php în browserul dvs. Ar trebui să vedeți mai întâi acest lucru:
Acest lucru sa întâmplat deoarece nu am creat încă clasa noastră de cărți de oaspeți. Pentru a face acest lucru, creați guestbook.php în dosarul dvs. de clase. Clasa ar trebui să conțină metodele pe care intenționăm să le folosim, dar nu ar trebui să conțină nimic la început. Țineți minte, mai întâi scriem testele inainte de scriind orice cod.
Când executați din nou testul, ar trebui să pară așa:
După cum vedem aici, testul nostru este acum câștigat prin eșec. Aceasta înseamnă că testul nostru este acum pregătit pentru a primi răspuns ".
Imagine de la http://www.gamercastnetwork.com/forums
Pasul 5. Răspundeți-vă testul scriind codul
La un moment dat, cu toții am simțit acest lucru atunci când programăm.
Imagine de la http://fermentation.typepad.com/fermentationAcum, că avem un test automat de lucru, putem începe să scriem cod. Deschide-ți guestbook.php clasați și începeți să creați răspunsul la testul dvs..
"Kirk", "mesaj" => "Bună, eu sunt Kirk." ), array ('name' => 'Ted', 'message' => 'Bună ziua, eu sunt Ted')); funcția publică viewAll () // Aici, ar trebui să preluăm toate înregistrările din baza de date. // Aceasta se simulează prin returnarea sumelor $ _entries return return self :: $ _ entries; funcția publică adăugă ($ name, $ message) // Aici simulează inserarea în baza de date prin adăugarea unei noi înregistrări în $ _entries array // Acesta este modul corect de a face acest lucru: self :: $ _ entries [ = array ('name' => $ nume, 'mesaj' => mesaj $); auto :: $ _ intrări [] = array ('notname' => $ name, 'notmessage' => mesaj $); // oops, există un bug aici undeva return adevărat; funcția publică deleteAll () // Tocmai am setat matricea $ _entries pentru a simula self :: $ _ entries = array (); return true;Această clasă guestbook.php are unele bug-uri în ea în scop, așa că putem vedea cum arată dacă testul nostru eșuează.
Odată ce ne facem testul, ar trebui să vedem ceva de genul:
Ieșirea de testare ne arată în ce test și în care afirmația noastră a eșuat. Din aceasta, putem observa cu ușurință că linia 16 și 17 este afirmația care a aruncat eroarea.
assertTrue (isset ($ intrare [ 'nume'])); $ This-> assertTrue (isset ($ intrare [ 'mesaj'])) ;?Acest lucru ne spune în mod clar că matricea de intrare returnată nu a avut cheia de matrice corectă. Pe baza acestui fapt, vom ști cu ușurință care parte din codul nostru a mers prost.
$ nume, 'mesaj' => $ mesaj); //fix! return true; ?Acum, când conducem din nou testul, ar trebui să ne arate:
Pasul 6. Refactor și perfecționează codul
Imagini sunt multumite de http://www.osborneink.com si http://phuketnews.phuketindex.comDin moment ce codul pe care îl testăm aici este destul de simplu, testarea noastră și fixarea bug-urilor nu a durat foarte mult. Dar dacă aceasta ar fi o aplicație mai complexă, va trebui să faceți mai multe modificări în codul dvs., să îl faceți mai curat, astfel încât să fie mai ușor de întreținut și multe alte lucruri. Problema cu aceasta, însă, este că schimbarea introduce de obicei bug-uri suplimentare. Aici intră testul nostru automatizat - odată ce facem schimbări, putem face din nou testul. Dacă încă mai trece, înseamnă că nu am nimicit nimic. Dacă eșuează, știm că am făcut o greșeală. De asemenea, ne informează unde este problema și, sperăm, cum o vom putea rezolva.
Pasul 7. Clătiți și repetați
Imagine de la http://www.philstockworld.comÎn cele din urmă, atunci când programul dvs. necesită funcționalități noi, va trebui să scrieți noi teste. Asta e ușor! Clătiți și repetați procedurile de la pasul doi (deoarece fișierele dvs. SimpleTest ar trebui deja configurate) și începeți din nou ciclul.
Concluzie
Există mult mai multe articole de dezvoltare în profunzime, bazate pe testare, și chiar mai multă funcționalitate pentru SimpleTest decât ceea ce a fost afișat în acest articol - lucruri precum obiecte machete, stubs, care fac mai ușor crearea testelor. Dacă doriți să citiți mai mult, pagina de dezvoltare bazată pe test Wikipedia vă va stabili pe calea cea bună. Dacă sunteți interesat să utilizați SimpleTest ca cadru de testare, căutați documentația online și asigurați-vă că ați examinat celelalte funcții.
Testarea este o parte integrantă a ciclului de dezvoltare, totuși este prea adesea primul lucru care trebuie tăiat atunci când termenele limită sunt iminente. Sperăm că, după ce ați citit acest articol, veți aprecia cât de util este să investiți în dezvoltarea bazată pe teste.
Care sunt gandurile tale privind dezvoltarea bazata pe teste? Este ceva care vă interesează implementarea sau credeți că este o pierdere de timp? Anunță-mă în comentariile!