Scrie testele de unitate profesională în Python

Testarea este fundamentul dezvoltării software solide. Există multe tipuri de testare, dar cel mai important tip este testul unității. Unitatea de testare vă oferă o mare încredere că puteți folosi piesele bine testate ca primitive și să vă bazați pe ele atunci când le compuneți pentru a vă crea programul. Acestea vă sporesc inventarul de cod de încredere dincolo de sistemele încorporate ale limbii dvs. și biblioteca standard. În plus, Python oferă un suport deosebit pentru testarea unităților de testare.

Exemplu de rulare

Înainte de scufundări în toate principiile, euristica și orientările, să vedem un test reprezentativ în acțiune. SelfDrivingCar clasa este o punere în aplicare parțială a logicii de conducere a unei mașini cu autovehicul. Se ocupă în cea mai mare parte cu controlul vitezei mașinii. Este conștient de obiectele din fața sa, de limita de viteză și de faptul dacă a ajuns sau nu la destinație. 

Clasa de autoDrivingCar (obiect): def __init __ (auto): self.speed = 0 auto.destination = Niciuna def _accelerate (auto): self.speed + = 1 def _decelerate (auto): if self.speed> 0: self.speed - = 1 def _advance_to_destination (self): distance = auto._calculate_distance_to_object_in_front () dacă distanța < 10: self.stop() elif distance < self.speed / 2: self._decelerate() elif self.speed < self._get_speed_limit(): self._accelerate() def _has_arrived(self): pass def _calculate_distance_to_object_in_front(self): pass def _get_speed_limit(self): pass def stop(self): self.speed = 0 def drive(self, destination): self.destination = destination while not self._has_arrived(): self._advance_to_destination() self.stop() def __init__(self): self.speed = 0 self.destination = None def _accelerate(self): self.speed += 1 def _decelerate(self): if self.speed > 0: auto.speed - = 1 def _advance_to_destination (self): distance = auto._calculate_distance_to_object_in_front () dacă distanța < 10: self.stop() elif distance < self.speed / 2: self._decelerate() elif self.speed < self._get_speed_limit(): self._accelerate() def _has_arrived(self): pass def _calculate_distance_to_object_in_front(self): pass def _get_speed_limit(self): pass def stop(self): self.speed = 0 def drive(self, destination): self.destination = destination while not self._has_arrived(): self._advance_to_destination() self.stop() 

Iată un test unitar pentru Stop() metodă pentru a vă alimenta apetitul. Voi intra mai târziu în detalii. 

de la testul unic de testare TestCase clasa SelfDrivingCarTest (TestCase): def setUp (auto): self.car = SelfDrivingCar () def test_stop (auto): self.car.speed = 5 auto.car.stop () # Verificați viteza este 0 după (0, auto.car.speed) # Verificați dacă este OK să opriți din nou dacă autovehiculul este deja oprit self.car.stop () self.assertEqual (0, auto.car.speed)

Instrucțiuni pentru testarea unităților

comite

Scrierea testelor bune de unitate este o muncă grea. Scrierea unităților de testare durează timp. Când faceți modificări în codul dvs., va trebui de obicei să vă schimbați și testele. Uneori veți avea erori în codul dvs. de testare. Asta înseamnă că trebuie să fii cu adevărat angajat. Beneficiile sunt enorme, chiar și pentru proiectele mici, dar nu sunt gratuite.

Fiți disciplinat

Trebuie să fii disciplină. Fii consistent. Asigurați-vă că testele trec mereu. Nu lăsați ca încercările să fie întrerupte deoarece știți că codul este OK.

Automatizați

Pentru a vă ajuta să fiți disciplinați, ar trebui să vă automatizați testele pentru unități. Testele ar trebui să ruleze automat la puncte semnificative, cum ar fi pre-comiterea sau pre-implementarea. În mod ideal, sistemul de gestionare a controlului sursei respinge codul care nu a trecut toate testele.

Codul netestat este rupt de definiție

Dacă nu l-ai testat, nu poți spune că funcționează. Aceasta înseamnă că ar trebui să consideri că este rupt. Dacă este un cod critic, nu-l utilizați în producție.

fundal

Ce este o unitate?

O unitate în scopul testării unității este un fișier / modul care conține un set de funcții sau o clasă asociate. Dacă aveți un fișier cu mai multe clase, trebuie să scrieți un test de unitate pentru fiecare clasă.

La TDD sau nu la TDD

Dezvoltarea bazată pe test este o practică în care scrieți testele înainte de a scrie codul. Există câteva avantaje pentru această abordare, dar vă recomand să o evitați dacă aveți disciplina de a scrie teste adecvate mai târziu. 

Motivul este că am design cu cod. Scriu cod, uite la el, rescrie-l, te uiți la el din nou și rescrie-l din nou foarte repede. Scrierea testelor mă limitează și mă încetinește. 

Odată ce am terminat proiectul inițial, voi scrie testele imediat, înainte de integrarea cu restul sistemului. Acestea fiind spuse, este o modalitate excelentă de a vă prezenta testele unității și vă asigură că tot codul dvs. va avea teste.

Modulul de test pentru unitate

Modulul moduletest vine cu biblioteca standard a Python. Oferă o clasă numită testcase, de la care poți să-ți iei clasa. Apoi puteți să o înlocuiți pe a înființat() - metoda de pregătire a dispozitivului de încercare înainte de fiecare încercare și / sau a classSetUp () pentru a pregăti un dispozitiv de testare pentru toate testele (nu se resetează între teste individuale). Sunt corespunzătoare dărâma() și classTearDown () metode pe care le puteți suprascrie, de asemenea.

Iată părțile relevante ale noastre SelfDrivingCarTest clasă. Eu folosesc doar înființat() metodă. Eu creez o proaspătă SelfDrivingCar și păstrați-l în self.car astfel încât este disponibil pentru fiecare test.

de la unitatea de testareTestCase de testareAutoDrivingCarTest (TestCase): def setUp (self): self.car = SelfDrivingCar ()

Următorul pas este de a scrie metode de testare specifice pentru a testa codul în curs de testare - SelfDrivingCar clasa în acest caz - face ceea ce trebuia să facă. Structura unei metode de testare este destul de standard:

  • Pregătirea mediului (opțional).
  • Pregătiți rezultatul așteptat.
  • Apelați codul testat.
  • Afirmați că rezultatul real corespunde rezultatului așteptat.

Rețineți că rezultatul nu trebuie să fie rezultatul unei metode. Poate fi o schimbare de stat a unei clase, un efect secundar cum ar fi adăugarea unui rând nou într-o bază de date, scrierea unui fișier sau trimiterea unui e-mail.

De exemplu, Stop() metodă a SelfDrivingCar clasa nu returnează nimic, dar modifică starea internă prin setarea vitezei la 0. The assertEqual () metoda oferită de testcase clasa de bază este utilizată aici pentru a verifica această chemare Stop() a lucrat cum era de așteptat.

def test_stop (self): self.car.speed = 5 auto.car.stop () # Verificați dacă viteza este 0 după ce ați oprit auto.asertEqual (0, auto.car.speed) # Verificați dacă este OK să opriți din nou dacă mașina este deja oprită auto.car.stop () self.assertEqual (0, auto.car.speed)

Există de fapt două teste aici. Primul test este să vă asigurați că dacă viteza mașinii este de 5 și Stop() se numește, atunci viteza devine 0. Apoi, un alt test este să se asigure că nu se întâmplă nimic în caz de apel Stop() din nou când mașina este deja oprită.

Mai târziu, voi introduce mai multe teste pentru funcționalități suplimentare.

Modulul Doctest

Modulul doctest este destul de interesant. Vă permite să utilizați eșantioane de coduri interactive în docstring și verificați rezultatele, inclusiv excepțiile ridicate. 

Nu folosesc și nu recomand doctest pentru sistemele de mari dimensiuni. Testarea unitară corespunzătoare necesită multă muncă. Codul de testare este de obicei mult mai mare decât codul testat. Docstrings nu sunt doar mediul potrivit pentru scrierea de teste cuprinzătoare. Sunt totuși cool. Iată ce a factorial funcția cu teste doc arată ca:

import math def factorial (n): "" "Returnați factorialul lui n, un număr exact> = 0. Dacă rezultatul este suficient de mic pentru a se potrivi într-un int, returnați un int. (n) pentru n în intervalul (6)] [1, 1, 2, 6, 24, 120] >>> [ 6, 24, 120] >>> factorial (30) 265252859812191058636308480000000L >>> factorial (30L) 265252859812191058636308480000000L >>> factorial (-1) Traceback (ultimul apel final): ... ValueError: n trebuie să fie> = 0 Factoriali ai flotorilor sunt valabile, dar floatul trebuie să fie un număr exact: >>> factorial (30.1) Traceback (cel mai recent apel ultimul): ... ValueError: n trebuie să fie întregul exact >>> factorial (30.0) 265252859812191058636308480000000L Nu trebuie să fie ridicol de mare : >>> factorial (1e100) Traceback (ultimul apel ultimul): ... OverflowError: n prea mare "" "dacă nu n> = 0: ridica ValueError (" n must be> = 0 ") math.floor )! = n: ridica ValueError ("n trebuie să fie întregul exact") dacă n + 1 == n: # captura o valoare ca 1e300 raise OverflowE rror ("n prea mare") rezultat = 1 factor = 2 în timp ce factor <= n: result *= factor factor += 1 return result if __name__ == "__main__": import doctest doctest.testmod()

După cum puteți vedea, docstring-ul este mult mai mare decât codul funcției. Nu promovează lizibilitatea.

Exerciții de testare

O.K. Ai scris testele tale. Pentru un sistem mare, veți avea zeci / sute / mii de module și clase peste eventualele directoare multiple. Cum conduceți toate aceste teste?

Modulul unittest oferă diverse facilități pentru a grupa testele și a le executa programabil. Verificați testele de încărcare și de alergare. Dar cea mai ușoară cale este descoperirea testelor. Această opțiune a fost adăugată numai în Python 2.7. Înainte de 2.7 puteți folosi nasul pentru a descoperi și pentru a rula teste. Nasul are câteva alte avantaje cum ar fi funcționarea funcțiilor de testare fără a fi nevoie să creați o clasă pentru cazurile dvs. de testare. Dar, în scopul acestui articol, să rămânem cu testul unitar.

Pentru a descoperi și a rula testele bazate pe unitatea de testare, pur și simplu tastați pe linia de comandă:

python -m unittest descoperi

unittest va scana toate fișierele și sub-directoarele, va executa orice teste pe care le găsește și va oferi un raport frumos, precum și timpul de execuție. Dacă doriți să vedeți ce teste se execută, puteți adăuga -v flag:

python -m unittest descoperi -v

Există mai multe steaguri care controlează operația:

python -m unittest -h Utilizare: python -m unittest [opțiuni] [teste] Opțiuni: -h, --help Afișați acest mesaj -v, --verbose Ieșire verbală -q, -quiet Ieșire minimă -f, - failfast Stop la prima eșec -c, - captură Control de captură-C și rezultatele afișării -b, --buffer Tampon stdout și stderr în timpul testărilor Exemple: python -m unittest test_module - executați testele de la test_module python -m unittest module.TestClass - executați teste de la module.TestClass python -m unittest module.Class.test_method - executați metoda de testare specificată [teste] poate fi o listă a oricărui număr de module de testare, clase și metode de testare. Utilizare alternativă: python -m unittest descoperi [opțiuni] Opțiuni: -v, -verbose Output verbose -f, -failfast Stop la prima eșec -c, --catch Catch control-C și rezultatele afișării -b, -buffer Tampon stdout și stderr în timpul testărilor - cu directorul Directory pentru a începe descoperirea ("." "Default") -p pattern Pattern pentru a se potrivi cu fișierele test ("test * .py") -t directorul Directorul de nivel superior al proiectului ) Pentru descoperirea testelor, toate modulele de testare trebuie să poată fi importate din directorul de nivel superior al proiectului.

Testarea testului

Testarea de testare este un câmp de multe ori neglijat. Acoperire înseamnă cât de mult din codul dvs. este testat de testele dvs. De exemplu, dacă aveți o funcție cu if-else declarație și încercați numai dacă ramură, atunci nu știți dacă altfel sucursala funcționează sau nu. În următorul exemplu de cod, funcția adăuga() verifică tipul argumentelor sale. Dacă ambele sunt numere întregi, le adaugă. 

Dacă ambele sunt șiruri, încearcă să le convertească la numere întregi și le adaugă. În caz contrar, se ridică o excepție. test_add () funcționează testele adăuga() funcția cu argumente care sunt ambele întregi și cu argumente care sunt flotante și verifică comportamentul corect în fiecare caz. Dar acoperirea testului este incompletă. Cazul argumentelor de șir nu a fost testat. Ca rezultat, testul trece cu succes, dar nu a fost descoperită tipologia din ramificația unde argumentele sunt ambele șiruri (vezi "intg" acolo?).

(a, int) și isinstance (b, int): returnați un a și b poate avea numere întregi (a, b): " (b), int: a întoarce int (a) + intg (b) altceva: a ridica excepția ("Argumentele nevalide") Test (unittest.TestCase): def test_add : self.assertEqual (5, adăugați (2, 3)) self.assertEqual (15, add (-6, 21)) self.assertRaises (excepție, add, 4.0, 5.0) 

Aici este rezultatul:

---------------------------------------------------------------------- Testul Ran 1 în 0.000s OK Procesul a terminat cu codul de ieșire 0

Instrucțiuni pentru unitatea de mâini

Scrierea testelor de rezistență industrială nu este ușoară sau simplă. Există mai multe lucruri de luat în considerare și se pot face compromisuri.

Proiectare pentru testare

Dacă codul dvs. este codul spaghetti formal sau o minge mare de noroi în care diferite niveluri de abstractizare sunt amestecate împreună și fiecare bucată de cod depinde de fiecare altă bucată de cod, veți avea dificultăți în încercarea acestuia. De asemenea, ori de câte ori schimbați ceva, va trebui să actualizați și o grămadă de teste.

Vestea bună este că design-ul software general cu scop general este exact ceea ce aveți nevoie pentru testabilitate. În special, un cod modular bine adaptat, în care fiecare componentă are o responsabilitate clară și interacționează cu alte componente prin intermediul unor interfețe bine definite, va face testarea testelor unice bune o plăcere.

De exemplu, ale noastre SelfDrivingCar clasa este responsabilă pentru funcționarea la nivel înalt a mașinii: mergeți, opriți, navigați. Are o calculate_distance_to_object_in_front () care nu a fost încă implementată. Această funcționalitate ar trebui probabil implementată de un subsistem complet separat. Poate include citirea datelor de la diferiți senzori, interacțiunea cu alte autoturisme, o stivă de vizionare a întregii mașini pentru analizarea imaginilor de la mai multe camere.

Să vedem cum funcționează acest lucru în practică. SelfDrivingCar va accepta un argument numit object_detector care are o metodă numită calculate_distance_to_object_in_front (), și va delega această funcție la acest obiect. Acum, nu este nevoie să unitate test acest lucru pentru că object_detector este responsabil (și ar trebui să fie testat) pentru aceasta. Totuși, doriți să testați faptul că utilizați object_detector cum se cuvine.

clasa SelfDrivingCar (obiect): def __init __ (auto, object_detector): self.object_detector self.speed = 0 self.destination = Niciun def _calculate_distance_to_object_in_front (self): return self.object_detector.calculate_distance_to_object_in_front

Cost / Beneficiu

Cantitatea de efort pe care o puneți în testare trebuie să fie corelată cu costul eșecului, cât de stabil este codul și cât de ușor este să remediați dacă problemele sunt detectate pe linie.

De exemplu, clasa noastră de auto-conducere este super critică. În cazul în care Stop() metoda nu funcționează corect, mașina noastră de auto-conducere ar putea ucide oamenii, ar putea distruge proprietatea și ar putea deraja întreaga piață de autovehicule. Dacă dezvoltați o mașină cu auto-conducere, bănuiesc că unitatea ta testează Stop() metoda va fi un pic mai riguroasă decât a mea. 

Pe de altă parte, dacă un singur buton din aplicația dvs. web de pe o pagină care este îngropat de trei niveluri sub pagina dvs. principală scutură puțin atunci când cineva face clic pe el, puteți remedia acest lucru, dar probabil nu va adăuga un test dedicat pentru acest caz. Economia pur și simplu nu o justifică. 

Testarea gândirii

Testarea mentalității este importantă. Un principiu pe care îl folosesc este că fiecare bucată de cod are cel puțin doi utilizatori: celălalt cod care îl folosește și testul care îl testează. Această regulă simplă ajută foarte mult la design și la dependențe. Dacă vă amintiți că trebuie să scrieți un test pentru codul dvs., nu veți adăuga o mulțime de dependențe dificil de reconstituit în timpul testelor.

De exemplu, presupuneți că codul dvs. trebuie să calculeze ceva. Pentru a face acest lucru, trebuie să încărcați unele date dintr-o bază de date, să citiți un fișier de configurare și să consultați în mod dinamic unele aplicații REST API pentru informații actualizate. Toate acestea pot fi necesare din diverse motive, dar punerea tuturor acelora într-o singură funcție va face destul de dificilă unitatea de testare. Este încă posibil să fii batjocorit, dar este mult mai bine să îți structurizi codul corect.

Funcții pure

Codul cel mai ușor de testat este funcțiile pure. Funcțiile pure sunt funcții care accesează numai valorile parametrilor, nu au efecte secundare și returnează același rezultat ori de câte ori sunt chemați cu aceleași argumente. Ele nu schimbă starea programului dvs., nu accesează sistemul de fișiere sau rețeaua. Beneficiile lor sunt prea multe pentru a conta aici. 

De ce sunt ușor de testat? Deoarece nu este nevoie să setați un mediu special de testat. Trebuie doar să treci argumentele și să testezi rezultatul. De asemenea, știți că atâta timp cât codul testat nu se schimbă, testul dvs. nu trebuie să se schimbe. 

Comparați-l cu o funcție care citește un fișier de configurare XML. Testarea dvs. va trebui să creeze un fișier XML și să treacă numele său de fișier la codul testat. Nu e mare lucru. Dar presupunem că cineva a decis că XML este abominabil și că toate fișierele de configurare trebuie să fie în JSON. Ei fac afaceri și convertesc toate fișierele de configurare în JSON. Ei conduc toate testele, inclusiv testele tale și ei toate trece! 

De ce? Deoarece codul nu sa schimbat. Încă se așteaptă un fișier de configurare XML, iar testul dvs. încă construiește un fișier XML pentru el. Dar în producție, codul dvs. va primi un fișier JSON, pe care nu îl va analiza.

Testarea erorilor

Eroarea de manipulare este un alt lucru care este critic pentru a testa. Este, de asemenea, parte din design. Cine este responsabil pentru corectitudinea intrării? Fiecare funcție și metodă ar trebui să fie clare în legătură cu aceasta. Dacă este responsabilitatea funcției, aceasta ar trebui să-și verifice intrarea, dar dacă este responsabilitatea apelantului atunci funcția poate merge doar despre afacerea sa și presupune că intrarea este corectă. Corectitudinea generală a sistemului va fi asigurată prin testarea apelantului pentru a verifica dacă trece doar intrarea corectă în funcție.

De obicei, doriți să verificați intrarea pe interfața publică pentru codul dvs. deoarece nu știți neapărat cine va apela codul. Să ne uităm la conduce() metoda auto-conduce masina. Această metodă așteaptă un parametru "destinație". Parametrul "destinație" va fi utilizat mai târziu în navigație, dar metoda de efectuare a acțiunii nu face nimic pentru a verifica dacă este corectă. 

Să presupunem că destinația ar trebui să fie o tuplă de latitudine și longitudine. Există tot felul de teste care pot fi efectuate pentru a verifica dacă este valabilă (de ex. Destinația în mijlocul mării). Pentru scopurile noastre, asigurați-vă că este vorba de o tuplă de plutitoare în intervalul de la 0,0 la 90,0 la latitudine și -180,0 la 180,0 la longitudine.

Aici este actualizat SelfDrivingCar clasă. Am implementat trivial unele dintre metodele neimplementate pentru că conduce() Metoda numește unele dintre aceste metode direct sau indirect.

clasa SelfDrivingCar (obiect): def __init __ (auto, object_detector): self.object_detector = obiect_detector self.speed = 0 self.destination = Nici unul def _accelerate (self): self.speed + = 1 def _decelerate (self) viteză> 0: auto.speed - = 1 def _advance_to_destination (self): distance = auto._calculate_distance_to_object_in_front () dacă distanța < 10: self.stop() elif distance < self.speed / 2: self._decelerate() elif self.speed < self._get_speed_limit(): self._accelerate() def _has_arrived(self): return True def _calculate_distance_to_object_in_front(self): return self.object_detector.calculate_distance_to_object_in_front() def _get_speed_limit(self): return 65 def stop(self): self.speed = 0 def drive(self, destination): self.destination = destination while not self._has_arrived(): self._advance_to_destination() self.stop()

Pentru a testa modul de gestionare a erorilor în test, voi trimite argumente nevalide și vom verifica dacă sunt respinse corespunzător. Puteți face acest lucru folosind self.assertRaises () Metodă de unittest.TestCase. Această metodă reușește dacă codul testat ridică o excepție.

Să o vedem în acțiune. test_drive () metoda trece latitudine și longitudine în afara intervalului valid și se așteaptă ca conduce() metodă de ridicare a unei excepții.

de la unitatea de testareTestCase de la importul self_driving_car de import de autoDrivingCar clasa MockObjectDetector (obiect): def calc_distance_to_object_in_front (auto): return 20 clasa SelfDrivingCarTest (TestCase): def setUp (auto): self.car = SelfDrivingCar (MockObjectDetector ()) def test_stop (self) auto.car.speed = 5 auto.car.stop () # Verificați dacă viteza este 0 după oprirea autoturismului.suntEqual (0, auto.car.speed) # Verificați dacă este OK să opriți din nou dacă autovehiculul este deja oprit. car.stop () self.assertEqual (0, auto.car.speed) def test_drive (self): # Destinație valabilă auto.car.drive ((55.0, 66.0)) # Gama nevalidă greșit destinație self.assertRaises .car.drive, (-55.0, 200.0))

Testul eșuează, deoarece conduce() metoda nu își verifică argumentele privind validitatea și nu ridică o excepție. Ai un raport frumos cu informații complete despre ceea ce a eșuat, de unde și de ce.

python -m unittest descoperi -v test_drive (untitled.test_self_driving_car.SelfDrivingCarTest) ... FAIL test_stop (untitled.test_self_driving_car.SelfDrivingCarTest) ... ok ======================= =============================================== FAIL: test_drive (untitled.test_self_driving_car.SelfDrivingCarTest) ------------------------------------------- --------------------------- Traceback (cel mai recent apel ultimul): Fișierul "/Users/gigi/PycharmProjects/untitled/test_self_driving_car.py" , linia 29, în test_drive self.assertRaises (excepție, auto.car.drive, (-55.0, 200.0)) AssertionError: excepția nu a fost ridicată -------------------- -------------------------------------------------- Ran 2 teste în 0.000s FAILED (eșecuri = 1)

Pentru ao rezolva, hai să actualizăm conduce() pentru a verifica efectiv gama argumentelor sale:

def drive (auto, destinație): lat, lon = destinație dacă nu (0.0 <= lat <= 90.0): raise Exception('Latitude out of range') if not (-180.0 <= lon <= 180.0): raise Exception('Latitude out of range') self.destination = destination while not self._has_arrived(): self._advance_to_destination() self.stop()

Acum, toate încercările trec.

python -m unittest descoperi -v test_drive (untitled.test_self_driving_car.SelfDrivingCarTest) ... ok test_stop (untitled.test_self_driving_car.SelfDrivingCarTest) ... ok ----------------------- ----------------------------------------------- Ran 2 teste în 0.000s OK 

Testarea metodelor private

Ar trebui să testați fiecare funcție și metodă? În special, ar trebui să testați metode private numite numai de codul dvs.? Răspunsul tipic nesatisfăcător este: "Depinde". 

Voi încerca să fiu util aici și să vă spun de ce depinde. Știi exact cine îți numește metoda privată - este codul tău propriu. Dacă testele dvs. pentru metodele publice care vă apelează la metoda dvs. privată sunt exhaustive, atunci vă testați metodele private în mod exhaustiv. Dar dacă o metodă privată este foarte complicată, poate doriți să o testați independent. Folosește-ți judecata.

Cum să organizați testele unității

Într-un sistem mare, nu este întotdeauna clar cum să vă organizați testele. Ar trebui să aveți un fișier mare cu toate testele pentru un pachet sau un fișier de testare pentru fiecare clasă? În cazul în care testele se află în același fișier ca și codul testat sau în același director?

Aici este sistemul pe care îl folosesc. Testele ar trebui să fie complet separate de codul testat (de aici nu folosesc doctest). În mod ideal, codul dvs. ar trebui să fie într-un pachet. Testele pentru fiecare pachet ar trebui să fie într-un director frate al pachetului dvs. În directorul de teste, ar trebui să existe un fișier pentru fiecare modul al pachetului dvs. numit Test_

De exemplu, dacă aveți în pachet trei module: module_1.py, module_2.py și module_3.py, ar trebui să aveți trei fișiere de testare: test_module_1.py, test_module_2.py și test_module_3.py în directorul de teste. 

Această convenție are mai multe avantaje. Se clarifică doar prin căutarea directoarelor că nu ați uitat să testați complet modulul. De asemenea, ajută la organizarea testelor în bucăți rezonabile. Presupunând că modulele dvs. sunt dimensionate în mod rezonabil, atunci codul de testare pentru fiecare modul va fi în fișierul propriu, care poate fi puțin mai mare decât modulul testat, dar încă ceva care se potrivește confortabil într-un singur fișier. 

Concluzie

Testele unice reprezintă fundamentul unui cod solid. În acest tutorial, am analizat câteva principii și linii directoare pentru testarea unităților și am explicat raționamentul din spatele mai multor bune practici. Cu cât este mai mare sistemul pe care îl construiți, cu atât testele unității mai importante devin. Dar testele unitare nu sunt suficiente. Alte tipuri de teste sunt necesare și pentru sistemele de mari dimensiuni: teste de integrare, teste de performanță, teste de sarcină, teste de penetrare, teste de acceptare etc.. 

Cod