Unitatea-testare și c ceea ce mock obiecte de exemplul Google c-cadru bate joc

Scopul testării unității - pentru a verifica separat programul „unități“, de exemplu, metode de clasă. În acest caz, testul nu ar trebui să „meargă dincolo de“ aceste metode. Dar acest lucru este mai ușor de zis decât de făcut.

Clasele folosesc adesea în punerea lor în aplicare a celorlalte clase, și ei, la rândul lor, includ mai multe clase. Din moment ce aproape toate programele folosesc biblioteca și diferitele platforme - o astfel de situație este naturală. O caracteristică rară este complet izolată de „lumea exterioară“ -, dar că lumea nu ar trebui să fie acoperite de teste o unitate!

instrument

Numirea Google de testare, de asemenea, că a Boost.Test sau CppUnit - Dezvoltarea de teste unitare. Oricare dintre aceste biblioteci se descurcă cu această sarcină. Cu toate acestea, în testul Google include un supliment special numit „C ++ Mocking Framework Google“ (în mod specific în acest articol nu este o diferență semnificativă între conceptele de „cadru“ și „bibliotecă“ - îmi cer scuze). ++ Mocking Framework C Google (denumit în continuare pur și simplu Google Mock) nu poate funcționa separat de la Google de testare, așa că, dacă aveți de gând să utilizați acest instrument, este necesar să se colecteze ambele proiecte. Nu e greu. În ansamblu, proiectul are o bună documentare (în limba rusă, de asemenea), aproximativ 800 de întrebări cu tag-ul Google de testare pe StackOverflow. un număr suficient de articole. Vom lua în considerare Google Mock, care vă permite să creați și să utilizați mock obiecte în teste unitare.

Pentru a înțelege de ce avem nevoie de mock obiecte în unitate de testare, avem nevoie de un exemplu simplu.

Imaginați-vă că suntem în curs de dezvoltare o clasă numită comandă (personalizate), și are mai multe functii membre: verifica - pentru verificarea comenzii, plata - pentru plata, anulare - de a anula, și multe altele, care pot fi asociate cu ordinea . Să presupunem că punerea în aplicare a metodelor este un foarte non-triviale. teste de unitate trebuie să verifice - dacă îndeplinesc în mod corect aceste funcții pe un set diferit de date de intrare. Sarcina standardului. Cu toate acestea, există o nuanță.

În cadrul punerii în aplicare a metodelor de clasă Ordine, a folosit clasa obiect Database (baza de date). Această clasă încapsulează unele de comunicare cu un magazin de date, și fiecare operațiune a ordinului, inițiază un apel la acest spațiu de stocare. Clasa Baza de date execută necunoscute pentru noi, „magic“, necesită o bază de date „live“, și în general nu proiectat de noi și alte departamente. Testele noastre unitare pentru comanda nu ar trebui să fie verificate chiar clasa baza de date. Mai mult decât atât, nu există nici o dorință de teste reale pentru a personaliza baza de date. Prin urmare, din baza de date de clasă reală nevoie pentru a scăpa de - să-l înlocuiască cu unele „fals“, o parodie, care are exact aceeași interfață ca și baza de date, dar, în realitate, face sau nu face nimic, ceea ce avem nevoie pentru a testa.

Notă: Este posibil să raskritikuete o legătură similară între Ordin și clasele de baze de date, dar nu înțelegeți greșit - aceasta este doar un exemplu.

Mai jos clase prezentate în mod convențional în discuție: Bază de date și de comandă.

Clasa de comandă poate lucra cu diferite implementari ale bazei de date și timpul de care avem nevoie pentru a face „fals“, atunci de ce nu-l vândă ei înșiși - fără ajutorul Google Mock. Doar creați o clasă DatabaseDummy. interfață deschisă cum ar fi baze de date, și-l va folosi în teste. Aceasta este o idee logică, dar nu este potrivit pentru testare. Iată de ce:

1) clasa DatabaseDummy trebuie să fie dezvoltate. Da - aceasta este doar o emulație, dar chiar este obositor să scrie. Posibil undeva „pentru a pune“ o greșeală - acesta este un proces plictisitor și inutil.

2) clasa DatabaseDummy nu trebuie doar să facă ceva, el ar trebui să fie în măsură să demonstreze un comportament diferit, așa că, dacă el este o adevărată bază de date. Acest comportament ar trebui să fie ușor de descris într-un anumit test. Cu alte cuvinte, clasa DatabaseDummy nu ar trebui să se comporte ca un „fals“, care răspunde întotdeauna în același mod. Și acest lucru este mai dificil de realizat.

Descris clasa DatabaseDummy - este fals clasa. dar nu și bate joc de clasă. Și aceste sensuri diferite de concepte. Puteți aduce, desigur, clasa DatabaseDummy la punctul în care va satisface cerințele noastre, dar am termina cu un cod suplimentar, care trebuie, de asemenea, să fie testate (aici o clătită). Iar dacă aveți, în plus față de baza de date, în punerea în aplicare care implică și alte obiecte, de exemplu, pentru rețea? Cât de mulți vor trebui să-și petreacă timpul ca vom scrie codul? Dacă vom folosi Google Mock, atunci totul va fi mult mai ușor. Google Mock ne va oferi de-a gata mock clase cu un efort minim de la noi puterea.

Cum va gestiona complet bate joc de clasa clasa baza de date, în cazul în care este de a încredința Google Mock? Iată cum:

Dacă scrie ceva greșit, veți primi o eroare la compilare, și este foarte bine.

Documentația descrie modul de a crea o machetă pentru clase diferite ocazii. De exemplu, dacă nu utilizați șabloane, și moștenirea. Dar, în realitate, procesul de învățare crearea mock clase cu ajutorul Google Mock durează câteva minute. Mult mai interesant apoi le folosesc în teste, deoarece comportamentul lor este complet subordonat noi. În afară de management machetă de site, puteți (și ar trebui) să specifice utilizarea intenționată - modul în care trebuie să fie numit de multe ori pe metoda de testare, ce argumente ar trebui să fie transferat. În cazul în care nu este executat ceva din setul de ipoteze, testul nu va fi trecut. Ne întoarcem acum la un exemplu simplu.

Verificați testa metoda din clasa comandă. In schimb Baza de date va folosi MockDatabase. Noi verifica dacă metoda de clasă make_query MockDatabase (și, prin urmare, clasa Database), acesta va fi numit pentru un test doar o singură dată. Valoarea primului argument sursă trebuie să fie egal cu „interogare“, iar al doilea argument, atunci când make_query apel, nu ne interesează. Cu toate acestea, ca urmare a unui apel make_query, al doilea argument trebuie să fie setat la „rezultat“, iar metoda ar trebui să se întoarcă adevărat.

La prima vedere, EXPECT_CALL expresie pare complicată și supraîncărcate. Cu toate acestea, am fost capabili să descrie într-o singură linie de comportament make_query a metodei de clasă bazei de date (MockDatabase) în acest test particular. În plus față de comportament, am identificat o serie de sugestii cu privire la modul de utilizare a metodei make_query se va produce: numărul de apeluri, valorile argumentelor trecut. Și toate într-o singură linie. De fapt, adevăratul test va avea mai multe expresii EXPECT_CALL pentru a descrie alte tehnici de clase de baze de date, ar determina secvența apelului lor.

Posibilitățile Google Mock în descrierea comportamentului pretins mock obiecte este foarte vastă. SetArgReferee. DOALL. Întoarcere - Această caracteristică a bibliotecii Google Mock. Lista completa de mare, dar pentru că poate fi foarte dificil să se stabilească comportamentul lor pentru mock obiecte. Cu toate acestea, în multe cazuri, ar fi de ajuns, și 10% din ceea ce este la Google Mock.

Rețineți că comportamentul nu este „cablată“ în mock-obiect, și este stabilit la începutul următorul test. Acest lucru permite flexibilitatea de a personaliza fiecare test în parte. De exemplu, în exemplul următor, ne așteptăm ca make_query metodă, în general, nu este cauzată de:

Ideea de bază este că, prin utilizarea o machetă de obiecte, nu ne concentrăm asupra punerii în aplicare a acestora și asupra comportamentului lor, precum și așteptările în ceea ce privește utilizarea testului. Ne place să descrie „mediul extern“ pentru codul de testare, izolați din toate dependențele, dar imita totul ca în cazul în care „mediul extern“ există (biblioteci, baze de date și rețea). Puteți crea chiar și excepții care sunt dificil de reprodus în realitate.

Din fericire, multe dezvolta teste unitare pentru programele lor. Dar nu întotdeauna când este oamenii știu despre mock obiecte. Sau le numesc „fals“ lipsesc doar oportunitățile pe care le oferă. Biblioteca pentru a crea și gestiona mock obiecte există în orice limbă. De exemplu, în Python (versiunea 3.3) este un unittest.mock modul standard. În Java acolo JUnit și JMock de expansiune. Chiar și pentru limbajul C a cmocka.org biblioteca. care susține mock obiecte. Google C ++ Mocking cadru nu este inferior lor în oportunități, dar rămâne destul de ușor de utilizat.

Scopul acestui articol a fost să atragă atenția asupra posibilității de a aplica mock obiecte în unitate de testare. Pe scurt spune despre una dintre cele mai eficiente instrumente. Asta e tot. Mult mai mult vă spun documentația în limba rusă:

Documentația privind Cadrul de testare Google C ++