pondělí 5. října 2009

Problémy s pokrytím kódu

Jednou z důležitých technik je sledování nakolik je aplikace pokryta testy. Můžeme sledovat kolik případů užití máme porytých, kolik zákazníkových požadavků, ale nejpřesnější alespoň co se týče pokrytí funkčnosti je pokrytí kódu.
Při zjišťování pokrytí kódu se zaznamenává, jaký kód byl při testování spuštěn a jaký naopak otestován ještě nebyl.

Nejjednodušší ale zároveň nedostačující a zavádějící je pokrytí příkazů - řádků.

To pouze kontroluje, zda daný příkaz, řádek, byl proveden v průběhu testování, pro pokrytí podmínky tak může stačit její libovolné vyhodnocení.

Formálně: T splňuje kritérium pokrytí příkazů pro daný kód K, jestliže pro každý příkaz p náležící kódu K existuje test t z množiny T, že při provedení t bude spuštěn příkaz p.

Pro testera nebo programátora není problém dosáhnout velmi vysokého (i 100 %) pokrytí příkazů programu plného chyb aniž by jediný test selhal, aniž by byla objevena jediná chyba. Přesto, že tato metrika je takto zavádějící, pro svou jednoduchost je i tak oblíbená.

O stupeň pokročilejší je pokrytí hran – rozhodnutí.

Formálně: Představme si graf, kdy příkazy tvoří uzly a možné přechody mezi nimi hrany. Pak za sebou provedené příkazy tvoří hranu a podmínka uzel, ze kterého vedou dvě hrany, jedna pro true a jedna pro false hodnotu. Pak množina testů T splňuje kritérium pokrytí hran pro daný kód K, jestliže pro každou hranu h výše popsaného grafu existuje test t z množiny T, že při provedení t projde výpočet hranou h.

Jednoduše řečeno u pokrytí hran je každá podmínka uzlem, ze kterého vedou dvě hrany.

Například:

Máme kód se třemi podmínkami, z nichž jedna je vnořená.



Graf pokrytí hran pak vypadá následovně:



Přitom modré kolečka představují podmínky, zelená ostatní příkazy.

Při jakýchkoli složitějších podmínkách je ale i toto pokrytí nedostatečné.

Další stupeň představuje pokrytí podmínek.

Formálně: Množina testů T splňuje kritérium pokrytí podmínek pro daný kód K, jestliže splňuje kritérium pokrytí hran a pro každou složenou podmínku platí, že pro každou její část p existují testy t, u z množiny T, že při provedení t se p vyhodnotí kladně a při provedení u záporně.

Pokud se vynechá část, že pokrytí podmínek musí splňovat pokrytí hran, tak k nepokrytí hran a pokrytí podmínek dochází v případě, že pro všechny možné vstupy je vždy celá podmínka vyhodnocena jako pravdivá nebo nepravdivá.

Vylepšení pokrytí podmínek spočívá v tom, že se berou v úvahu všechny možná vyhodnocení podmínky, nejen to, zda je pravdivá, či nikoli.

Například:

Mějme složenou podmínku if (a>0 || b>0).
K pokrytí hran by stačili tyto testy: {a = 5; b = -2}, {a = 0; b = 0}
K pokrytí podmínek by tyto testy nestačili, protože část b > 0 je v obou případech nepravdivá. Pokrytí podmínek lze však dosáhnout jinými dvěma testy: {a = 5; b = 2}, {a = 0; b = 0}

U této verze je už těžší najít chybu, kterou bychom plným pokrytím podmínek neodhalili, i když jisté typy chyb stále budou i v plně pokrytém kódu zůstávat.

Nejvyšší stupeň pokrytí je pokrytí cest, které sleduje všechny možné průchody kódem a proto představuje opravdu podrobné otestování.

Formálně: Množina testů T splňuje kritérium pokrytí cest pro daný kód K, jestliže splňuje kritérium pokrytí podmínek a pro každou cestu C v grafu kódu spojující vstupní a výstupní uzel grafu a obsahující nejvýše n cyklů existuje test t z množiny T, že při provedení t projde výpočet cestou C.

I když ne všechny chyby jdou odhalit pouze z kódu, pokrytí cest poskytuje jistotu, že byly otestovány všechny možnosti běhu. Problémem je praktická nepoužitelnost tohoto pokrytí, jelikož jeho složitost způsobuje exponenciální růst počtu testů.

Otázka 1: Kolik testů (průchodů kódem) je potřeba, aby měla metoda code_coverage pokryty příkazy; hrany; podmínky; cesty?



Otázka 2: Kolik testů (průchodů kódem) je potřeba, aby měla metoda code_coverage2 pokryty příkazy; hrany; podmínky; cesty?

2 komentáře:

  1. Pěkný příspěvek. Chvíli mi trvalo, než jsem přišel na to, v čem je pokrytí hran lepší než pokrytí příkazů. Pak mi to došlo, testují se i hrany, kde není žádný příkaz. Je to tak?

    OdpovědětVymazat
  2. Ano, dalo by se to tak chápat.
    Pokud máme následující příkaz, tak pro pokrytí příkazů nám stačí jeden test s libovolnou hodnotou proměnné a.
    if (a>5) then do_st;
    Pokud chceme ale pokrýt hrany, potřebujeme dva testy, jeden s a>5 a jeden s a<=5.

    OdpovědětVymazat

Oblíbené příspěvky