Kako automatski testovi menjaju pojam kvaliteta softvera
Zahvaljujući automatskim testovima možete na vreme, u ranoj fazi razvoja softvera, da identifikujete potencijalne probleme i da izmenite manjkavosti u kôdu.
Kada radite na velikim projektima sa javnom upravom i državnim institucijama, na jedno sigurno možete da računate: ono što je definisano na početku projekta podleže malim mogućnostima promene. Pod time se podrazumeva budžet koji je na raspolaganju, vreme u kome je neophodno završiti projekat i broj definisanih funkcionalnosti. Da biste sa predviđenim parametrima mogli uspešno da završite projekat, potrebno je da razvijete dobar plan od samog početka.
Na ovakvim, često višegodišnjim i izazovnim projektima rade timovi sastavljeni od velikog broja ljudi. Sa back end strane morate da obezbedite da poslovna logika funkcioniše, a sa front end strane da korisnički interfejs radi kako je zamišljeno. Zato je bitno da se automatski testovi uključe od samog starta razvoja softverskog sistema, da biste sa većom dozom sigurnosti mogli da kažete da su gore pomenute aktivnosti uspešno kompletirane.
Pisanje testova nije lak posao. Ako institucija za koju radite sama odabere i nametne tehnologiju u kojoj treba da razvijate softver onda ta ista tehnologija može da bude ograničavajući faktor za testiranje. S druge strane, kada sami birate tehnološko rešenje, javlja se dilema o optimalnoj tehnologiji za zadatak koji je ispred vas. Zato razvojni timovi koji razvoj baziraju na testovima, prilikom odabira tehnologije biraju one koje na jednostavan način omogućavaju njihovo pisanje i integraciju u softversko rešenje.
Pre, ili u toku pisanja automatskih testova, praksa je da se koriste i manuelni testovi. Oni mogu da budu neformalni, gde tester proverava da li je implementirana funkcionalnost u skladu sa dokumentacijom, ili formalni, gde se test sprovodi po unapred definisanom setu koraka, koji simuliraju ponašanje korisnika. Osnovni nedostatak ovih testova je njihova fokusiranost na proveru određene funkcionalnosti, pri čemu se celokupna slika sistema može lako izgubiti iz vida. Tako manuelnim testiranjem možete da potvrdite da je određeni deo softvera zadovoljavajući, ali da previdite da je narušeno funkcionisanje drugog dela sistema izazvano tom promenom. Ovo posebno važi u situacijama kada razvojni timovi generalizuju jednu funkcionalnost kako bi je koristili u više različitih modula. Te situacije su česte.
Zahvaljujući automatskim testovima možete na vreme, u ranoj fazi razvoja softvera, da identifikujete potencijalne probleme i da izmenite manjkavosti u kôdu.
Testovi mogu da se podelie u n kategorija, a ovde su navedeni oni koji se najčešće koriste u razvoju:
• Unit testovi (jedinični) koji služe za zasebno testiranje svake programske komponente tj. funkcionalnosti nezavisno od ostalih delova sistema;
• Integracioni testovi koji proveravaju da li sistemske komponente sarađuju, kao što je opisano u specifikacijama dizajna sistema i programa. Njima se testira sve, od korisničkog interfejsa do baze podataka i služe za simulaciju rada korisnika;
• Funkcionalnim testovima proverava se da li integrisani sistem zaista izvršava funkcije opisane u specifikaciji zahteva. Tokom razvoja, najčešće su pokriveni integracionim testovima;
• Performance testovi kojima se testiraju performanse softverskog rešenja.
Praksa je pokazala da su potrebna dva tipa scenarija za pravilno testiranje određene funkcionalnosti tj. slučaja korišćenja:
• Pozitivni test koji predstavlja osnovni scenario korišćenja softvera. Kada korisnik ispoštuje sva pravila i unese sve podatke na predviđeni način ovaj test proverava da li je rezultat u skladu sa očekivanim. Jedan scenario može da ima desetine poslovnih pravila koja moraju da budu zadovoljena. Dobra praksa je testiranje što većeg broja slučajeva, ako ne i svih poslovnih pravila, kako bi se na vreme identifikovali propusti.
• Negativni test predstavlja alternativna scenarija u kojima je osnovna pretpostavka da neće sve da prođe kao što je očekivano.
Zašto je testiranje bitno?
Testiranje omogućava da se tokom razvoja i pisanja testova pravovremeno identifikuju problemi u arhitekturi softverskog rešenja, funkcionalnoj specifikaciji i sl. Takođe, ako je pisanje automatskih testova komplikovano, to može da ukaže da je početna pretpostavka, postavka sistema ili slučaj korišćenja previše komplikovan i da bi ga trebalo uprostiti.
Pisanje testova samo po sebi povećava vreme razvoja i implementacije. Koliko mogu da produže razvoj zavisi od složenosti sistema i potrebe da se on testiranjem pokrije.
Bolje definisanje opsega potrebnih testova na samom početku razvoja, pomoći će programerima da kreiraju kvalitetne testove i daju bolju procenu vremena potrebnog za njihov razvoj. Na dobru procenu i korišćenje vremena utiče i broj testova koji se sprovode. Pisanje testova da bi se zadovoljio njihov određeni broj je kontraproduktivna praksa. Oni moraju da imaju definisanu svrhu, da budu jednostavni i imaju smisla.
Zašto je bitno da se sa manuelnih pređe na automatske testove?
Ako svaki programer piše automatske testove, proverava ih i pokreće na svojoj lokalnoj mašini, biće u mogućnosti da ustanovi greške u svom segmentu i ispravi ih. Ono što predstavlja problem je izvršavanje svih testova lokalno. Tada je njihovo izvršavanje vezano za razvojno okruženje, koje gotovo nikada nije isto kao produkciono, i samo izvršavanje testova bi trajalo jako dugo, što produžava vreme trajanja razvoja. Iz tog razloga, praksa je da se testovi izvršavaju na serverima namenjenim za kontinuiranu integraciju (Continuous Integration).
Continuous Integration (CI) koncept najčešće funkcioniše na jednoj mašini i jednom serveru, sa jednim centralnim repozitorijumom gde se čuva kôd aplikacije.
Kada bilo koji programer promeni deo koda, server nadograđuje aplikaciju i pravi izvršni fajl nad kojim se sprovode testovi. Nakon završene provere server šalje informaciju da je test uspešan ili neuspešan, i programer koji je inicirao pokretanje testova u realnom vremenu zna da li je narušio neki test ili neku funkcionalnost i odmah može da ispravi grešku. Proces pokretanja testova se ponavlja tokom dana, nakon svake izmene koda, ali i uz mogućnost da se kreira plan periodičnog izvršavanja različitih vrsta testova. Da ne bi blokirali rad, za testove koji se dugo izvršavaju uglavnom se postavljaju planovi periodičnog izvršavanja, dok se kratki testovi izvršavaju nakon svake promene.
CI takođe povećava verovatnoću da se problem otkrije u ranoj fazi razvoja softvera. To je posebno važno za projekte na kojima treba da se razviju hiljade funkcionalnosti i kod kojih je vrlo teško pronaći i ispraviti grešku nakon što je aplikacija puštena u produkciju.
Automatsko testiranje omogućava dobijanje informacije o procentu pokrića softvera testovima tj. test coverage. Procenat pokrića uglavnom postavljaju klijenti, na početku projekta ili već pri samom tenderu i on može da bude drugačiji za različite delove softverskog sistema.
Prilikom pravljenja izvršnog fajla i izvršavanja testova, postoje alati koji daju statistiku o pokrivenosti svakog dela sistema. U Sagi se u te svrhe koristi Maven kao alat za automatsku pripremu izvršnog fajla aplikacije i Cobertura i JaCoCo plug-inovi za praćenje statistike pokrivenosti testovima. Dobra praksa je da se na startu projekta postavi neki manji procenat koji će se kasnije povećavati.
Usvajanjem prakse pisanja i izvršavanja automatskih testova gradi se kultura u kojoj razvojni tim prihvata da su oni bitan i prateći deo tokom čitavog procesa razvoja softvera.
Testovi generalno vode ka boljem dizajnu aplikacije. Od posebnog značaja je da se ne zaboravi da će na aplikaciji, nakon implementacije i puštanja u produkciju, raditi veliki ili veći broj korisnika pa je neophodno da se testovima proveri i konkurentan rad, tj. da li u takvim uslovima sistem funkcioniše. Tako sprečavate da u radu aplikacije dođe do nekonzistentnosti baze podataka.
Šta nakon produkcije?
Manuelno sprovođenje testova nakon puštanja softvera u produkciju je teži deo procesa testiranja i on mora da postoji. Automatski testovi tada dolaze do izražaja, jer se nakon izmena u kodu, njihovim izvršavanjem zna da li je narušen neki deo sistema. U ovoj fazi uglavnom se koriste regresioni testovi, koji služe za proveru narušenosti sistema.
Definisanje kolika je potreba za testovima, pokrivenosti aplikacije sa njima i planiranog vremena koje može da se utroši u razvoju testova u fazi dizajna arhitekture sistema, umnogome će olakšati posao razvojnim timovima, ali i dati precizniju informaciju klijentu o vremenu završetka posla i najčešće utiče i na utisak koji se ostavlja kod klijenta.
Jako je bitno da svi uključeni u aktivnosti razvoja testova, a naročito programeri, prihvate značaj njihovog pisanja. To će im, na duže staze, olakšati posao, povećati kvalitet koda i njihovu sigurnost u ono što su uradili, jer se funkcionalna specifikacija često menja, pa samim tim i kôd, a testovi su jedini način da se brzo utvrdi da li izmena koja je napravljena funkcioniše ili je narušila neki deo sistema. Klijentu, sa druge strane, daje sigurnost da je željeni softver proizvod ozbiljnog, predanog i sistematičnog rada.