You are on page 1of 46

Testiranje softvera

Unit testiranje u Python-u,


unittest biblioteka
Unit testiranje

• Testiranje, uopšte o u programerskom smislu, je praksa pisanja koda


(odvojena od stvarnog koda aplikacije) koja poziva kod koji će da
testira kod aplikacije kako bi utvrdili da li postoje greške
• Ne dokazuje da je kod ispravan (što je oguće samo u vrlo
ogra iče i okolnostima). On samo izveštava da li se kod izvršava nad
uslovima koje je tester definisao
Unit testiranje
• Koje stvari mogu biti uhvaćene kroz testiranje?
• Sintaksne greške su nenamerne greške u pisanju(kao na primer ekstra
(.) u lista..append(foo))
• Logičke greške nastaju kada algoritam (koji se ože smatrati
" ači o rešava ja problema") nije tača . Možda je programer
zaboravio na to da u Python-u indeksiranje kreće od nule i pokušao je
da šta pa poslednji karakter u nizu pisanjem ispisa
(string[len(string)]) (što će uzrokovati povećanje indeksa)
• Moguće je proveriti i veće sistemske greške. Možda program nikad ne
radi kada korisnik unese broj veći od 100, ili se čeka na odgovor veb
sajta koji nije dostupan
Unit testiranje

• Sve ove greške mogu se uhvatiti pažljivi testiranjem koda


• Unit testiranje (testiranje jedinice), posebno testira jedinstvenu
"jedinicu" koda u izolaciji. Jedinica ože biti čitav modul, jedna klasa
ili funkcija, ili bilo šta iz eđu
• Ono što je važ o, eđuti , jeste da je kod izolovan od drugog koda
koji ne testiramo (što ože dovesti do grešaka i time uticati na
rezultate testa)
Unit testiranje

• Testiranje osigurava da kod pravilno radi pod određe i skupom


uslova
• Sintaksne greške će gotovo sigurno biti uhvaćene testiranjem, a
osnovna logika jedinice koda ože se ustanoviti kako bi se osigurala
ispravnost pod određe i uslovima
• Ponovo, ne radi se o dokazivanju da je kod tača pod bilo kojim
uslovima. Postoji namera da se ponudi razumno kompletan skup
ogućih uslova (npr. Može se napisati test za ono što se dešava kada
se pozove sabiranje(3, 'frižider’ , ali ne moraju se testirati svi mogući
stringovi za svaki argument)
Unit testiranje

• Testiranje o ogućava korisniku da obezbedi da promene koda ne


utiču na već postojeću funkcionalnost
• Ovo je posebno korisno prilikom refaktoriranja koda. Bez testiranja,
ne postoje nikakve garancije da promena koda ne utiče na delove koji
su prethodno radili
• Za ovo je potrebno pravilno testiranje jedinice
Unit testiranje

• Testiranje tera da se raz išlja o kodu pod eo ič i uslovima,


eventualno otkrivajući logičke greške
• Za dobro testiranje potreban je modularni, razdvojeni kod, što je znak
dobrog dizajna sistema. Cela svrha testiranja jedinice jeste rad sa
kodom koji je labavo povezan (loosely coupled). Ako aplikacijski kod
ima direktne pozive prema bazi podataka, na primer, testiranje logike
aplikacije zavisi od toga da li je dostupna validna veza sa bazom
podataka i testnim podacima u bazi podataka
Unit testiranje

• unittest, okruže je za unit testiranje, originalno je inspirisan JUnit-om


i jako je sliča ostalim glavnim okruže ji a za testiranje jedinice u
drugim programskim jezicima.
• Podržava automatizaciju testova, deljenje setup-a i shutdown koda za
testiranje, agregaciju testova u kolekcije i nezavisnost testova od
okruže ja o kojima izveštava
Unit testiranje
• unittest podržava neke važ e koncepte objektno-orijentisanog
programiranja:
• Priprema testa - predstavlja pripremu koja je potrebna za izvođe je jednog ili
više testova, kao i bilo kakve akcije čišćenja. Ovo ože uključiti, na primer,
kreiranje privremenih ili proxy baza podataka, direktorijuma ili pokretanje
servera
• Test case - pojedi ač a jedinica za testiranje. Proverava spe ifiča odgovor za
određe i skup inputa. Unittest o ez eđuje osnovnu klasu, TestCase, koja se
ože koristiti za kreiranje novih testnih slučajeva
• Test suite - kolekcija testnih slučajeva, testnih suite-a ili oboje. Koristi se za
sakupljanje testova koji treba da se izvrše zajedno
• Test runner - komponenta koja upravlja izvrše je testova i daje ishod
korisniku. Runner ože koristiti grafički interfejs, tekstualni interfejs ili vratiti
posebnu vrednost kako bi ukazao na rezultate izvršava ja testova
Unit testiranje
• Pogledajmo primer
Unit testiranje

• unittest je dio Python standardne


biblioteke
• Unit test se sastoji od jedne ili više
tvrdnji (assert , izjave koje tvrde da
je neko svojstvo, dio testiranog
koda istinit). Reč "tvrdi" bukvalno
z ači "da je či je i a". To su i
tvrdnje u unit testovima
Unit testiranje
• self.assertTrue tvrdi da je argument koji mu se
prosleđuje evaluira na True. Klasa unittest.TestCase
sadrži brojne (assert) metode za tvrđenje, zato je
potrebno proveriti listu metoda i izabrati
odgovarajuću za test
• Korišćenje assertTrue-a za svaki test je loše jer
povećava optereće je za onoga koji čita testove.
Pravilnom upotrebom metoda tvrđe ja eksplicitno
navodimo tač o ono što se testira (npr. Jasno je šta
assertIsInstance() govori o svom argumentu samo
gledanjem na ime metoda
Unit testiranje

• Svaki test bi trebalo da testira jedinstvenu


osobinu koda i da bude imenovan prema
tome. Da bi bio pro ađe po oću
jedinstvenog mehanizma za otkrivanje
testova (prisutan u Pithon 2.7+ i 3.2+),
metode testiranja trebaju da sadrže kao
prefiks test_ (ovo se ože konfigurisati,
ali svrha je da se razlikuju testne metode i
ostale)
Jednostavan ači pokretanja testova,
o ez eđuje interfejs komandne linije za
test skriptu
Unit testiranje

Exception

• U ovom primeru testiramo


samo funkciju „prostBroj “.
Kada bi pokrenuli skriptu
test_python.py dobili bi
sledeće:
Unit testiranje
• Ovaj rezultat pokazuje da je aš unit test
rezultovao neuspehom ne zbog neuspeha
tvrdnje, već zbog toga što je se pojavio
izuzetak. Zapravo, unittest nije dobio
priliku da pravilno proveri aš test zbog
izuzetka
• Greška se ispravlja tako što će o staviti da
opseg kreće od 2

Tačka ako je uspeš o izvrše test


Unit testiranje

• A šta ako bi prosledili neke negativne


brojeve
• Test eće proći, ali Python ne vraća
jasan odgovor na kom testu je pao
• Korišće je msg parametra koji prima
funkcija assertFalse() da bi nam
ukazao gde se javila greška

F - fail
Unit testiranje
Unit testiranje
• Sada kad smo uvidili da postoji
greška, ostalo je samo da je
reši o. U ovom slučaju
dodaće o samo još jedan if u
definiciji funkcije za raču a je
prostog broja
Unit testiranje
• Primeri ajčešće korišće ih
assert metoda
• assertEqual() – proverava da
li je izlaz jednak sa
očekiva i rezultatom
• assertTrue() i assertFalse() –
proverava uslov
• assertRaises() – provera da li
određe i izuzetak iskače
Unit testiranje
• Pokretanje testova iz CLI (Command Line Interface)
• Unittest modul se ože koristiti iz komandne linije za pokretanje
testova iz modula, klasa ili čak pojedi ač ih testnih metoda:

• Testove je moguće pokretati tako da dobijamo više detalja


dodavanjem oznake -v:

• Za listu dodatnih opcija


Unit testiranje
• Organizovanje koda
• Osnovni gradivni blokovi unit testiranja su testni slučajevi (test cases)
- pojedi ač i scenariji koji moraju biti podeše i i provereni za ispravan
rad.
• U unittest modulu, testni slučajevi su predstavljeni preko instance
unittest.TestCase. Da bi sami pisali sopstvene testove, date klase će
morati asleđivati ovu klasu (TestCase) ili treba koristiti
FunctionTestCase
• Testni kod TestCase instance mora biti potpuno sa oodrživ, tako da
se ože pokrenuti bilo u izolaciji ili u proizvoljnoj kombinaciji sa bilo
kojim drugim testnim slučajevi a
Unit testiranje

• Imajte na umu da, da bi ešto testirali, koristimo jednu od metoda


assert * () koju nudi TestCase bazna klasa
• Ako test ne uspije, izuzetak će se podići i unittest će identifikovati
testni slučaj kao neuspeh. Svi drugi izuzeci će se tretirati kao greške
• Klasa TestCase pruža nekoliko assert metoda za proveru i prijavljivanje
grešaka. Tabela na narednom slajdu navodi ajčešće korišćene
metode:
Unit testiranje
Metoda Proverava
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)
Unit testiranje
• Sve assert metode prihvataju argument msg koji je, ako je naveden,
nam daje na uvid poruku o greš i
• Takođe je oguće proveriti bilo kakvu pojavu izuzetaka, upozorenja i
log poruka koristeći sledeće metode:
Metoda Proverava
assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) raises exc
assertRaisesRegex(exception, regex, fun, *args, fun(*args, **kwds) raises exc and the message
**kwds) matches regex r
assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) raises warn
assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) raises warn
fun(*args, **kwds) raises warn and the
assertWarnsRegex(warn, r, fun, *args, **kwds)
message matches regex r
The with block logs on logger with minimum
assertLogs(logger, level)
level
Unit testiranje

• Kod poslednje navedenih metoda veoma često se koristi context


manager. On će sačuvati uhvaće i izuzetak u njegovom izuzetak
atributu. Ovo ože biti pogodno kada je potrebno da se izvrše
dodatne provere nakon što se izuzetak pojavi

• Napomena: msg parametar se ože prosleđivati ovim metodama


samo ako se koristi context manager
Unit testiranje
• Primer: testiranje funkcija za
sabiranje, oduzimanje, ože je
i deljenje
Unit testiranje
• assertEqual() – proverava da li su dva
prosleđe a argumenta jednaka
• assertRaises() – proverava da li se
pojavljuje izuzetak za prosleđe o

Četiri tačke za četiri testa koja su napisana i koja


su uspeš o odrađe a. Iako u sklopu jednog testa
imam više puta potiv assert metode, i dalje se na
njega posmatra kao na samo jedan test
Ako se ova skripta pokrene direktno, main() će
nam o ogućiti automatsko izvršava je svih
testova (tamo gde stoji prefiks test_)
Unit testiranje
• Kada bi imali grešku u kodu,
unittest bi nam je automatski
prijavio

Ne iskače izuzetak
za ove vrednosti
Unit testiranje

Bez context manager-a Sa context manager-om


Unit testiranje

• Posmatrajmo sada
primer na klasi
Unit testiranje Stalno se ponavlja ovaj
kod u svakoj funkciji

Vrši se proveravanje kreiranja mejla na osnovu imena


i prezimena, provera punog imena kao i poviše ja
plate
Unit testiranje
• Ono što je primetno jeste da se jedan te isti kod ponavlja u svakoj
testnoj metodi. Praksa je takva da što je manje koda to je bolje
• Takođe kada se vrši više testiranja o ič o se izvršavaju nad istim
objektima, tako da ako bi se taj objekat promenio iz jednog mesta,
hteli bi smo da se ta promena propagira svuda. Za ovo nam služe
setUp() i tearDown() metode
• setUp() – metoda za pripremu pre testiranja. Poziva se neposredno
pre pozivanja testnih metoda. Osim AssertionError ili SkipTest, bilo
koji izuzetak koji se desi dok se izvršava ova metoda s atraće se
greško umesto neuspehom testa
• Default-na implementacija ne radi išta
Unit testiranje

• tearDown() – poziva se odmah nakon što je pozvana testna metoda i


rezultat je za eleže . Ona će se pozvati čak iako je tokom testiranja
došlo do pojave izuzetja, tako da bi implementacija u podklase trebala
biti aročito oprezna u pogledu provere u utraš jeg stanja
• Bilo koji izuzetak, osim AssertionError ili SkipTest, podignut ovom
metodom, s atraće se dodatnom greško , a ne greško tokom
testiranja (time se potencijalno povećava ukupan broj prijavljenih
grešaka). Ovaj metod će se pozvati samo ako setUp () uspe, bez obzira
na ishod metode testiranja
• Default-na implementacija ne radi išta
Unit testiranje
• Sada imamo funkcije setUp() i
tearDown() koje se izvršavaju
pre i posle svakog testiranja
• Nije potrebno više da u svakoj
funkciji uvodimo novog
zaposlenog, to će o sada
raditi sve u SetUp() gde će o
imati instance atribute, dok bi
u tearDown() mogli da se
rešava o nepotrebnih resursa
• U svaku metodu smo dodali
šta pa je da bi smo vidili
redosled izvršava ja
Unit testiranje
setUp() i tearDown() koji
se izvršavaju pre svakog
testa

Ne treba nikada
pretpostaviti da se
testovi izvršavaju
redom kroz skriptu
(zato testovi trebaju
da budu izolovani)
Unit testiranje
• Takođe pogodno bi imati metode koje će da se izvršavaju pre bilo kog
testa, pre ičega, i nakon svakog testiranja. Za to nam služe metode
setUpClass() i tearDownClass()
• setUpClass() - metoda klase koja se poziva pre svih testova u
pojedi ač oj klasi. setUpClass() se poziva u klasi kao jedini argument i
mora biti imat dekorator @classmethod
• tearDownClass() - metoda klase koja se poziva nakon svih testova u
pojedi ač oj klasi. tearDownClass() se poziva u klasi kao jedini
argument i mora biti imat dekorator @classmethod
Unit testiranje
Unit testiranje

• Preskakanje testova i očekiva e greške


• Unittest podržava preskakanje pojedi ač ih testova i čak čitavih klasa
testova. Pored toga, podržava o eležava je testa kao "očekiva og
neuspeha", test koji je loš i koji će podbaciti, ali koji se ne treba
raču ati kao neuspeh na TestResult-u
• Preskakanje testa je o oguće o korište jem dekoratora skip () ili
jedne od njegovih uslovnih varijanti
Unit testiranje
• @ unittest.skip (razlog)
• Bezuslovno preskoče oz ače i test. Razlog bi trebao opisati zašto je test
preskoče
• @ unittest.skipIf (uslov, razlog)
• Preskače oz ače i test ako je uslov tača
• @ unittest.skipUnless (uslov, razlog)
• Preskače oz ače i test ako uslov nije tača
• @ unittest.expectedFailure
• Oz ačava test kao očekiva i neuspeh. Ako test ne uspe, test se ne raču a kao
neuspeh
• exception unittest.SkipTest(reason)
• Izuzetak je podignut da preskoči test
• O ič o se koristi TestCase.skipTest () ili jedan od dekoratora za preskakanje umesto da ga
direktno podignete
Unit testiranje

• Preskoče i testovi eće imati


setUp() ili tearDown() da se
pokreću oko njih. Preskoče e
klase eće imati setUpClass()
ili tearDownClass() koji se
izvršavaju
Unit testiranje

• Moguće je i preskakanje
klase koristeći skip dekorator
Unit testiranje
• Grupisanje testova – klasa TestSuite
• Ova klasa predstavlja skup svih pojedi ač ih testnih slučajeva
(TestCase-ova) i testnih grupa (TestSuite-a). Klasa predstavlja interfejs
potreban testeru kako bi o ogućio da se pokrene kao bilo koji drugi
test slučaj. Pokretanje TestSuite instance je isto kao prolaz kroz tu
grupu (suite), i pokretanje svakog testa pojedi ač o
• Ako su testovi dati, mora biti o oguće o iteriranje kroz pojedi ač e
testne slučajeve ili druge grupe, a koji će biti korišće i za počet u
inicijalizaciju grupe (suite-a). Dodatne metode su o ez eđe e kako bi
kasnije bili u ogić osti da dodajemo testne slučajeve i grupe
Unit testiranje
• Objekti TestSuite klase po ašaju se kao TestCase objekti, osim što oni
zapravo ne sprovode test. Umesto toga, koriste se za grupisanje
testova u grupe, a koji trebaju biti pokretani zajedno. Neke od
dodatnih metoda za dodavanje testova:
• addTest (test)
• Dodaje TestCase ili TestSuite u suite (grupu)
• addTests (testovi)
• Dodaje sve testove iz TestCase-a i TestSuite instance u ovaj test suite
• Ovo je ekvivalentno iteriranju kroz testove, pozivajući addTest() za svaki
element
Unit testiranje
• run(rezultat)
• Pokretanje testova vezanih za ovu
grupu, prikupljanje rezultata u
objektu test result koji se prenosi
kao rezultat

Kreiranje instance
TestSuite i dodavanje
testova iz klasa
Suite se izvršava pozivanjem metode run() iz klase
TextTestRunner() (zato imamo njenu instancu runner)

run() metoda kreira instancu TestSuite-a, pokreće


testove i šta pa rezultate
Unit testiranje
• Zadatak 1: Napisati program koji će da testira svaku metodu iz Zadatka
1 sa prethodnih vež i (klasa Krug)
• Zadatak 2: Napisati program koji će da testira Zadatak 3 sa prethodnih
vež i (klasa KompleksniBroj). Takođe, potrebno je napraviti grupu
testova (TestSuite) koja će da se sastoji od svih testova iz prvog
zadatka (test_povrsina() i test_obim()) kao i testova za sabiranje i
oduzimanje kompleksnih brojeva
• Zadatak 3: O ogućiti preskakanje svih testova iz klase KompleksniBroj
iz prethodnog zadatka

You might also like