Testovanie aplikácií je stále pre mnohých vývojárov a firmy neznámy pojem. Ak sa povie testovať, obyčajne sa tým myslí ručne „preklikať“ pred odovzdaním. Tento postup zlyháva, ak sa jedná o pravidelne vyvíjaný systém, ktorý sa zakaždým rozširuje. Nové funkcie môžu pokaziť tie staré, prípadne môžu zmeniť chovanie zdanlivo nesúvisiacich častí aplikácií. Takto sme chytení do bludného kruhu programovania nových funkcionalít, údržby starých a fixovania funkcií, ktoré sa zdanlivo náhodne pokazia. Vystúpiť z tohto kolobehu je možné napríklad automatizovaným testovaním aplikácií, ktoré v Barte používame na platforme Sportnet.

Prečo vlastne testovať?

Pravdepodobne si hovoríte, že testy nepotrebujete. Vitajte v klube, ani ja som ich nepotreboval – nebol som k testovaniu vedený, nikto ma ich neučil písať, ani mi nevysvetlil prečo mám kód testovať. Veď prečo písať automatizovaný test na niečo, čo programujem práve teraz? Ja predsa viem, že to funguje. Dokončil som funkcionalitu a posielam to klientovi na vyskúšanie. Tu a tam treba upraviť nejakú drobnosť, niekde niečo doplniť, niekde niečo odstrániť, zmeniť výpočet, ale inak môžeme nasadiť na ostrú verziu…

Po niekoľkých hodinách volá klient, že niečo nefunguje. Som presvedčený, že všetko bolo v poriadku, ale potlačím obrovskú chuť povedať jednu z viet: „u mňa to fungovalo“, „nič som nemenil“ alebo „pokazilo sa to asi po tom, čo sa zapracovali všetky pripomienky“ a radšej som chybu opravil a znova klikol na deploy. A potom znova. A znova…

Podobný scenár sme s kolegami zažili už toľkokrát, že sme si v kancli zriadili tabuľu, na ktorú sme pridali čiarku stále, keď sa niečo podobné stalo. Ako zdroj problému sme určili chýbajúce testy.

Po zopár desiatkách čiarok sa nám minula tabuľa. Prestali sme ich teda zapisovať a začali sme sa reálne zaoberať testingom.

Spôsoby testovania

Druhov a spôsobov testovania je neúrekom. My sme sa v kontexte testovania webových aplikácií zamerali na 4 a to:

  • manuálne testovanie,
  • e2e, aka „end to end“ testovanie,
  • integračné testovanie,
  • unit testovanie.

Manuálne testovanie prebieha „ručne“ – testovacie scenáre musí zakaždým prejsť človek – tester. Toto testovanie sa vyznačuje najdlhšou a najmenej presnou spätnou väzbou vývojárovi, no zároveň sa, ale jedná o jediný skutočný testing softvéru, pretože automatizované testy môžeme považovať len za nástroje, ktoré overujú, či systém funguje tak, ako bolo vyšpecifikované.

Problém automatizácie manuálneho testovania riešia e2e testy, kde tester predpíše scenár, ktorý následne vykonáva automatický softvér. Scenár môže vyzerať napríklad takto:

  1. choď na adresu http://www.***.sk/login
  2. klikni do textového poľa pre prihlasovacie meno
  3. zadaj prihlasovacie meno
  4. klikni do textového poľa pre prihlasovacie heslo
  5. zadaj heslo
  6. stlač tlačidlo „prihlásiť“
  7. očakávaj, že sa na obrazovke zjaví „ste prihlasený“.

V prípade, že takýto test prejde, pravdepodobne nám funkcionalita funguje. Nezahŕňa to však viacero špecifických prípadov, napríklad, že nemáme aktivované konto. Na to by sme museli napísať samostatný test.

Automatizovaný tester si tiež „nevšimne“, že i keď test prejde, so stránkou môže byť niečo v neporiadku, napríklad sa nevhodným použitím CSS formulár pre prihlasovanie vôbec nezobrazí.

Ak teda píšeme test pre E2E, obyčajne ním pokrývame tzv. „happy path“ a teda najpravdepodobnejší očakávateľný scenár.

Integračné testovanie už obyčajne nevykonávajú testeri, ale sami vývojári. Ide o testovanie, ktorého cieľom je overiť, či väčšie časti softvéru spolu fungujú. Príkladom môže byť testovanie, či sa dáta po registrácii zapíšu do databázy a či ich následne odtiaľ vieme bez problémov prečítať.

Unit testy testujú tok programu v jednotlivých funkciách na najnižšej možnej úrovni a kontrolujú všetky možné scenáre, ktoré môžu pri výkone funkcií nastať. Ideálny unit test je nezávislý na ostatných testoch a na zvyšku testovaného programu. Za účelom dosiahnutia nezávislosti sa vytvárajú pomocné objekty, ktoré simulujú predpokladaný kontext, v ktorom bude funkcia spúšťaná. Tento postup nazývame mocking.

Priznám sa, že v niektorých prípadoch nevidím rozdiel medzi integračným a unit testovaním a nie som prvý. Nie je ale dôležité ako sa testy volajú, je dôležité, čo robia.

It’s not important what you call it, but what it does – Gojko Azdic

Pyramída alebo zmrzlina?

Nasledujúci obrázok zobrazuje dva odlišné prístupy k pomeru jednotlivých druhov automatizovaných testov vrámci jedného projektu.

Pri odporúčanom postupe „pyramída“ najviac testujeme pomocou unit testov, ktoré tvoria základ všetkého testovania, a manuálne testujeme len minimum.

Druhý prístup, „zmrzlinový kornútok„, sa zameriava hlavne na manuálny testing a E2E testing. Hlavnou myšlienkou tohto prístupu je, že ak pokryjeme časť softvéru manuálne, príp. automatizovaným E2E testom, všetky podradené časti musia určite fungovať.

Kornútkový postup sa páči najmä:

  • vývojárom, pretože väčsina práce sa presúva na testerov,
  • manažérom, pretože tieto testy simulujú skutočné chovanie a preto vedia, akým spôsobom to ovplyvní koncového používateľa,
  • testerom, pretože sa nemusia zaoberať tým, či otestujú všetky možnosti ale len na to, aby otestovali minimum.
    Zdroj: https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html

Pre oba prístupy, kornútok aj pyramídu, platí, že čím vyššie v nich sa posúvame, tým:

  • majú testy dlhšiu spätnú odozvu,
  • sú testy vágnejšie,
  • je stále komplikovanejšie nasetupovať prostredie v ktorom bežia,
  • je ťažšie z konkrétneho zlyhávajúceho testu zistiť, kde presne nastala chyba,
  • pokrývajú stále väčšie časti softvéru,
  • častejšie sa stáva, že zlyhajú, aj keď pre používateľa sa nič nezmení.

Pritom pre pohodlný vývoj vývojári požadujú pravý opak, a to:

  • Rýchlu spätnú odozvu – možnosť spúšťať testy aj po každej zmene v kóde lokálne na svojom počítači s výsledkami dostupnými do niekoľkých milisekúnd až sekúnd.
  • Konkrétnu príčinu zlyhania – ak test zlyhá, nie je potrebné zdĺhavo debugovať, naopak, je jasné, v ktorom konkrétnom mieste test zlyhal a prečo (očakávaná vs. reálna hodnota).
  • Izoláciu testov – testy nie sú ovplyvnené vonkajšími vplyvmi a ich výstup sa v čase nemení, teda ich výsledok by mal byť rovnaký pri spustení v ľubovoľnom poradí, ľubovoľnom čase a na ľubovoľnom stroji.

Tieto požiadavky najlepšie pokrývajú uniť testy, čo vedie k uprednostneniu „pyramidového prístupu“ automatizovaného testovania. Ten sa aj u nás ukázal ako efektívnejší a už po niekoľkých mesiacoch nám ušetril desiatky hodín cyklického fixovania.

Viac testov, menšie náklady

Možno sa obávate, že vám testovanie zaberie veľa času, že si kvôli nemu nebudete stíhať plniť termíny, alebo že budete mať problém obhájiť zvýšené náklady pred klientom. Vo všetkých prípadoch máte pravdu. ALE pamätajte, že primárnym cieľom (dobrých) vývojárov a vývojarských firiem je odovzdávať kvalitný softvér, ktorý dlhodobo plní úlohu, pre ktorú bol naprogramovaný. 

Nemala by to byť otázka peňazí ani času. Ak na doručenie dlhodobo udržateľného softvéru potrebujete testy, musia byť zahrnuté v cene vývoja, rovnako, ako samotné písanie kódu.

Mohli by sme pohľad otočiť a povedať, že ak nepíšeme testy, klientovi spôsobujeme škodu, pretože v konečnom dôsledku zaplatí kvôli cyklickému fixovaniu funkcií viac peňazí, než by musel.

Záverom by som azda len poznamenal, že pokiaľ si myslíte, že viete dodať kvalitný softvér bez testov, tak ich proste nerobte. My sme im dali šancu a nám (aj nášmu klientovi) sa to oplatilo.

Chcete sa dozvedieť viac o našej práci?