Lekce 9 - Techniky testování bílé skříňky
V předchozí lekci, Testovací analýza a návrh testů, jsme si ukázali přehled testovacích technik a poté jsme se zaměřili na techniky testování černé skříňky.
V dnešní lekci o technikách white-box testingu si řekneme něco o testování a pokrytí příkazů, poté se zaměříme na testování a pokrytí větví a podíváme se na význam white-box testingu. Dalším tématem budou techniky experience-based testingu, odhadování chyb, průzkumné testování a nevynecháme ani testování založené na kontrolních seznamech.
Techniky white-box testingu
Dvěma nejběžnějšími technikami white-box testingu jsou statement testing (testování příkazů) a branch testing (testování větví), jež slouží k ověřování kódu:

White-box testing se však neomezuje pouze na tyto základní techniky a úroveň component testingu. Existují pokročilejší způsoby, které se používají v bezpečnostně, provozně nebo integračně kritických prostředích, kde je cílem dosáhnout vyššího stupně pokrytí. Tyto techniky se využívají také na vyšších úrovních testování a mohou zahrnovat i měření pokrytí, které není výhradně zaměřené na kód.
Pokrytí příkazů
Statement testing se zaměřuje na to, aby každý spustitelný příkaz v kódu byl alespoň jednou otestován. Cílem je navrhnout test casy, které dosáhnou určité úrovně pokrytí všech těchto příkazů. Míra pokrytí se vyjadřuje procentuálně – tedy jaká část z celkového počtu spustitelných příkazů byla skutečně při testování vykonána.
Když se podaří dosáhnout 100% pokrytí příkazů, znamená to, že každý spustitelný příkaz v kódu byl vykonán alespoň jednou. To pomáhá najít potenciální chyby, které by se mohly projevit při spuštění těchto příkazů.
Je však důležité vědět, že ani 100% pokrytí příkazů nezaručuje odhalení všech chyb – například chyby související se specifickými daty nebo kombinacemi podmínek. Navíc tato technika nemusí vždy pokrýt celou logiku rozhodování v kódu, protože některé větve (rozdílné podmínky nebo cesty) mohou zůstat netestované.
Pokrytí větví
Větev je místo v kódu, kde se může změnit směr vykonávání programu, což znamená, že kód se může vydat různými cestami. Představme si to jako křižovatku. Na každé křižovatce – větvi – může program jít rovně nebo odbočit podle podmínky. Tento přechod může být:
- Nepodmíněný – kód se vykonává bez podmínek, tedy lineárně (např. po jednom příkazu následuje přímo další).
- Podmíněný – kód se rozdělí podle výsledku nějakého rozhodnutí (např. je-li hodnota proměnné větší než 10, kód provede jednu akci, jinak provede jinou).
Při branch testingu se snažíme pokrýt všechny větve, tedy všechny možné cesty, kterými se kód může vydat. Cílem je vytvořit test casy tak, aby dosáhly pokrytí co nejvíce větví.
Pokrytí větví se měří jako procento všech větví, které byly otestovány. Stoprocentní pokrytí větví znamená, že byly otestovány všechny možné cesty, jimiž se kód může vydat. Nicméně i tehdy se může stát, že se neodhalí některé chyby, zvlášť ty, které se objeví jen při určité kombinaci cest.
Důležité je, že pokrytí větví automaticky zahrnuje i pokrytí příkazů. Když 100% pokryjeme větve, znamená to, že jsme automaticky prošli všemi příkazy kódu. Naopak to ale neplatí – úplným pokrytím příkazů nemusíme pojmout všechny možné cesty kódem, tedy větve.
Praktický příklad
Ukažme si na praktickém příkladu rozdíl mezi pokrytím příkazů a pokrytím větví. Máme e-shop a chceme dávat zákazníkům množstevní slevu, jestliže si nakoupí více než 10 kusů zboží:
public class KalkulackaObjednavky { public static double vypocetCeny(int mnozstvi, double cenaZaKus, double sleva) { double celkovaCena; if (mnozstvi > 10) { celkovaCena = mnozstvi * cenaZaKus * (1 - sleva); // Aplikujeme slevu, pokud je množství větší než 10 } else { celkovaCena = mnozstvi * cenaZaKus; // Bez slevy } return celkovaCena; } }
Metoda vypocetCeny
přijímá tři parametry. Množství, cenu
za kus a slevu, která se aplikuje pouze při nákupu více než 10 kusů. Pokud
je mnozstvi
větší než 10, slevu uplatníme. Jinak se cena
počítá bez slevy.

Pokrytí příkazů
Při pokrytí příkazů otestujeme metodu s parametry
vypocetCeny(15, 100, 0.1)
. Metoda tedy vykoná příkaz:
celkovaCena = mnozstvi * cenaZaKus * (1 - sleva);
První parametr metody je mnozstvi > 10
, čímž dosáhneme
100% pokrytí příkazů, protože každý spustitelný příkaz v metodě
vypocetCeny
je vykonán alespoň jednou.
Pokrytí větví
Pro 100% pokrytí větví musíme otestovat obě cesty v podmínce –
if (mnozstvi > 10)
i větev else
. Přidáme tedy
další testovací případ vypocetCeny(5, 100, 0.1)
. Ten vykoná
příkaz z větve else
:
celkovaCena = mnozstvi * cenaZaKus;
Jelikož je mnozstvi < 10
, zajistíme 100% pokrytí větví,
neboť máme testovací případy pro obě možné cesty v podmínce.
Význam white-box testingu
Hlavní výhodou technik white-box testingu je, že berou v úvahu implementaci softwaru, což usnadňuje odhalování defektů, zejména pokud je specifikace softwaru nejasná, zastaralá nebo neúplná. Slabou stránkou je, že tyto techniky nemusí odhalit defekty způsobené opomenutím implementace některých požadavků.
Tyto techniky lze využít při static testingu, například při revizi kódu nebo pseudokódu, kdy kód ještě není připraven ke spuštění. Umožňují také analyzovat logiku vyšší nebo nižší úrovně, která může být modelována pomocí grafu řídicího toku.
Na rozdíl od technik black-box testingu, které neodhalují míru pokrytí kódu, poskytuje white-box testing objektivní měření pokrytí kódu. Díky tomu poskytuje cenné informace pro vytváření dalších testů, které zvyšují pokrytí kódu a tím i důvěru v jeho správnost.
Techniky experience-based testingu
Nejznámější používané techniky experience-based testingu popsané v následujících kapitolách jsou bug estimation (odhadování chyb), exploratory testing (průzkumné testování) a checklist-based testing (testování založené na kontrolních seznamech).

Bug estimation
Bug estimation je technika používaná k předvídání výskytu chyb, defektů a selhání na základě znalostí testerů. Tato technika čerpá z:
- Toho, jak fungovala aplikace v minulosti.
- Typických vývojářských chyb a typických defektů, které jsou důsledkem těchto chyb.
- Typických selhání, která nastala v jiných aplikacích.
Chyby mohou souviset se vstupy, výstupy, logikou, výpočty, rozhraními nebo daty. Jednou z metod této techniky je útok na vady, při kterém testeři sestavují seznam potenciálních chyb, defektů a selhání. Na základě tohoto seznamu navrhují testy, které mají za cíl tyto problémy identifikovat, odhalit nebo vyvolat. Seznamy chyb mohou být sestaveny z osobních zkušeností, dat o defektech, selháních nebo z obecného pochopení příčin selhávání softwaru.
Praktický příklad
Představme si tým, který testuje nový modul e-shopu pro výpočet celkové ceny objednávky, včetně daní a slev. Testeři vědí, že v předchozích verzích aplikace se často objevovaly chyby spojené s nesprávným výpočtem DPH u různých typů zboží. Proto při test planingu navrhují scénáře, které se zaměří na správné uplatnění DPH u různých produktů.
Exploratory testing
Exploratory testing je metoda, při které jsou testy navrhovány, prováděny a vyhodnocovány v reálném čase, zatímco testeři získávají znalosti o testovaném objektu. Cílem je hlouběji prozkoumat software, odhalit dosud netestované oblasti a vytvořit cílené testy.
Exploratory testing lze strukturovat pomocí testování v relacích, kdy testeři pracují v definovaných časových úsecích a používají tzv. testovací listinu, která specifikuje cíle testování. Po relaci následuje debriefing, kde se diskutují výsledky se zainteresovanými stranami. Testovací relace jsou dokumentovány pomocí test session sheets, které zaznamenávají provedené kroky a zjištění.
Tato technika je užitečná v situacích, kdy specifikace chybí, je nedostatečná nebo kdy je na testování málo času. Exploratory testing může efektivně doplňovat jiné testovací techniky a je nejúčinnější, když jsou testeři zkušení, mají znalosti z domény a jsou vybaveni analytickými schopnostmi, zvídavostí a kreativitou.
Praktický příklad
Představme si, že tým testuje mobilní aplikaci pro rezervaci restaurací, ale dokumentace je nedostatečná a chybí podrobné specifikace funkcí.

Tester dostane 60 minut na prozkoumání části aplikace, která umožňuje uživatelům rezervovat stůl v restauraci. Bez předem definovaných test casů prochází aplikaci, zkouší různé scénáře. Tester má za cíl prozkoumat, jak se aplikace chová při změně rezervace, zrušení rezervace nebo při pokusu rezervovat restauraci, která je plně obsazená. Tento cíl je součástí jeho testovací listiny, která ho při testování vede. Po dokončení relace tester provede debriefing s vývojovým týmem, kde shrne svá zjištění. Tester také zdokumentuje kroky a chyby v test session sheet pro budoucí využití a případné opravy.
Checklist-based testing
Při checklist-based testingu testeři vytvářejí, implementují a provádějí testy za účelem pokrytí podmínek uvedených v kontrolním seznamu. Kontrolní seznamy vznikají na základě zkušeností testerů, znalostí o tom, co je důležité pro uživatele, nebo na základě pochopení důvodů, proč software selhává.
Kontrolní seznamy by měly být konkrétní a neobsahovat automatizovatelné položky, příliš obecné body nebo položky vhodné jako vstupní či výstupní kritéria. Položky jsou často formulovány jako otázky a mělo by je být možné ověřit odděleně. Kontrolní seznamy mohou zahrnovat požadavky, vlastnosti uživatelského rozhraní, kvalitativní charakteristiky a další formy testovacích podmínek. Podporují functional i non-functional testing:

Testovací tým projde každou položku seznamu a ověří, zda aplikace splňuje dané podmínky, přičemž výsledky testování zaznamená a kontrolní seznam pravidelně aktualizuje na základě nalezených problémů.
Postupem času mohou být některé položky méně efektivní, jelikož vývojáři se vyhýbají dřívějším chybám. Proto je důležité kontrolní seznamy pravidelně aktualizovat na základě analýzy defektů, přidávat nové položky podle závažnosti nově objevených chyb, ale také se vyvarovat nadměrného prodlužování seznamu.
V případech, kdy nejsou k dispozici podrobné test casy, může testování založené na kontrolních seznamech poskytnout určitý rámec a konzistenci. Protože jde však o obecné seznamy, může se objevit variabilita v test execution, což sice může vést k širšímu pokrytí, ale také k menší opakovatelnosti testů.
Zdrojem této lekce jsou Učební osnovy – Certifikovaný tester základní úrovně ver. 4.0. Copyright © 2023 autoři verze 4.0: Renzo Cerquozzi, Wim Decoutere, Klaudia Dussa-Zieger, Jean-François Riverin, Arnika Hryszko, Martin Klonk, Michaël Pilaeten, Meile Posthuma, Stuart Reid, Eric Riou du Cosquer (předseda), Adam Roman, Lucjan Stapp, Stephanie Ulrich (místopředseda), Eshraka Zakaria
V následujícím kvízu, Kvíz - Revize, návrh testů a white-box testing, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.