1. Testování Cíl látky Cílem tohoto bloku je seznámit studenty již na začátku kurzu s obecnými základy testování a též jak se testují třídy v objektovém programovacím jazyku Java.
1.1. Úvod do testování 1.1.1. Co je to testování Testováním se rozumí dokumentované uvedení programu nebo jeho jednotky do činnosti s cílem nalézt co možná nejvíce chyb. Při tvorbě samotného programu však programátor postupuje zcela opačně, protože vytváří zdrojové kódy požadované aplikace s cílem dosažení požadované funkce. Jakmile programátor si „myslí“, že dosáhl požadované chování, je uspokojen a nemá chuť již dále trápit své „dítko“ hledáním chyb. Zatímco tester přistupuje ke své úloze z úplně jiného pohledu. Jeho neuspokojuje, že program funguje, ale nachází smysl své práce právě v tom, že najde chybné chování testovaného programu. To, že najde chybu musí být odvozeno od nesplnění především specifikace požadavků a taky například od norem, zákonů a jiných relevantních omezení definované v zadání projektu. Velmi často se lze setkat s názorem, že právě když programátor provádí kontrolu chování svého programu tak, že testuje. Proč tomu nemůžeme říkat testování? Důvodem je to, že programátor provádí kontrolu chování programu proti tomu, jak on pochopil zadání. Zatímco tester porovnává chování programu s tím, jak on pochopil požadavky. Když se tyto dva děje se odehrávají fyzicky jiných osobách, je velká pravděpodobnost nalezení chyb v programu. Někdy to nemusí být jiné osoby a to tehdy pokud je vývoj řízen testy. Tím se se rozumí, že nejdříve se podle požadavků sestaví testy a teprve potom se přikročí k samotné tvorbě aplikačních zdrojových kódů. Tyto dva procesy jsou alespoň časově posunuty a nebo testy jsou přezkoumány někým jiným. Dobrý vývojářský tým si včas uvědomuje, že objem prací na testování může i několikanásobně přesáhnout objem prací na samotné tvorbě programového vybavení. Podcenění testování nám velmi často dokazují informace o neúspěšných projektech informačních systémů jak domácích, tak i zahraničních provedience.
1.1.2. Co je to chyba Definovat co je to chyba softwaru bývá obtížné, protože existuje spousta pohledů na to co je chyba. Už to vyplývá z toho, jak lze chybu pojmenovat: vada, závada, problém, omyl, událost, anomálie, odchylka, selhání, nekonzistence. Při výběru pojmenování chyby velmi záleží na firemní kultuře a taky na tom, aby se zmírnila negativní reakce odběratelů vyvíjeného softwaru. Například jedna 1
známa firma používá před zákazníky při výskytu chyby slova jako jsou situace, potíže, okolnosti, dočasně nereaguje, nefunguje spolu, neočekávaně se uzavře. Aby bylo možné definovat co je to chyba, musí se nejdříve vědět co se má vyvinout. To se zaznamenává do specifikace produktu neboli do požadavků na software. Pravidla pro uznání, že se jedná o chybu softwaru: 1. 2. 3. 4.
Software nedělá něco, co by podle specifikace produktu dělat měl. Software dělá něco, co by podle údajů ve specifikaci produktu dělat neměl. Software dělá něco, o čem se specifikace produktu nezmiňuje. Software něděla něco, o čem se specifikace produktu nezmiňuje, ale měla by se zmiňovat. 5. Software je obtížně srozumitelný, těžko se s ním pracuje, je pomalý, nebo - podle názoru testera softwaru - jej koncový uživatel nebude považovat za správný. Seznam největších chyb [http://www5.in.tum.de/~huckle/bugse.html]
1.1.3. Proč chyby vznikají Je zajímavé, že omyly při programování nejsou nejčastější příčinou vzniku chyb. Nejčastější příčinou vzniku chyb softwaru je specifikace. Proč tomu tak je? V řadě případů ji prostě nikdo nenapíše. Další příčinou může být, že specifikace není dostatčně podrobná, nebo se neustále mění, nebo se s ní dostatečně neseznámili všichni členové týmu. Plánování softwaru je jedna z nejdůležitějších činností, která rozhoduje o úspěchu. Jestliže se neprovádí správně, jsou do softwaru zanášeny chyby. Druhým největším zdrojem chyb je návrh. V něm programátoři popisují svůj plán jak bodou tvořit požadovaný software. Návrh lze přirovnat k výkresům budovy. Objektový návrh je dobré dělat v UML. V návrhu dochází k chybám zer stejných důvodů, proč vznikají i ve specifikaci: návrh je uspěchaný, často se mění, nebo není dostatečně prodiskutován, nebo se vůbec neprovádí a přímo se kóduje. Teprve třetí v pořadí jsou chyby, které vznikají v samotné tvorbě zdrojových kódů. Zde je příčinou nedostatečná dokumentace ( zejména v kódu, který se neustále aktualizuje nebo opravuje), časová tíseň v požadovaných termínech anebo to jsou prostě hloupé chyby. Je však nutné upozornit, že většina těchto chyb mají příčinu v omylech specifikace produktu a v návrhu. Nejméně početnou skupinou jsou chyby, které vznikají z ostatních příčin.
1.1.4. Náklady chyb Jedním z velmi důležitým faktorem, který může významně ovlivnit úspěch softwarového projektu jsou náklady na odstranění chyb. Platí pravidlo, že čím později se chyba odhalí, tím její oprava je dražší. Je dokázáno, že v náklady rostou desetinásobně každou etapou tj. specifikace, návrh, kódování, testování a uvedení do provozu. Takže pokud se odhalí chyba až když je produkt v nasazen, tak její oprava je ticíckrát dražší než, kdyby se přišlo na to, že je chybná specifikace. 2
1.1.5. Co je úkolem tester softwaru Když z předchozích odstavců je patrné co je to chyba a jak nákladné může být její odstranění, můžou se stanovit úkoly testera: 1. Cílem softwarového testera je vyhledávat chyby. 2. Cílem softwarového testera je vyhledávat chyby, a to vyhledávat co nejdříve. 3. Cílem softwarového testera je vyhledávat chyby, vyhledávat je co nejdříve a zajistit jejich nápravu
1.1.6. Jak se pozná dobrý softwarový tester? Mohlo by se zdát, že hledat chyby je jednoduché. Opak je pravdou. Vyžaduje to metodický a disciplinovaný přístup k testování softwaru. Vyžaduje stejné usílí a odhodlání jako samotné programování. Tester nemusí být zdatným programátorem, ale když je, je to výhoda. Dnes se již v mnohých firmách považuje testování softwaru za plnohodnotné technické inženýrské povolání. Seznam vlastností testera: • • • • • • •
Je zvídavý Rád se snaží přijít věcem na kloub Je neúnavný Je tvořivý Je perfekcionista (do rozumné míry) Je taktní a diplomatický Je přesvědčivý
Testování softaru je zábavné! Nejdůležitější vlastnosti softwarového testera je, že věci rád rozbijí a rozmontovává. Žije tím, že nějaký fantastický systém nachytá na hruškách a přivodí jeho havarii. Cítí obrovské uspokojení, může-li shodit ze stolu i ty nejsložitější programy. Často skáčou radostí, placají se vzájemně rukama a tancují, když srazí systém na kolena. Tato přirozená životní radost je na jejich práci zřejmě nejdůležitější.
1.2. Testování softwaru I když je softwarový projekt dobře naplánován, je vybrán vhodný model životního cyklu vývoje, tak v reálném životě nikdy se podle plánu plně nepostupuje a model životního cyklu se nedodržuje. Nikdy není k dispozici důkladná a podrobná specifikace, která dokonale odpovídá požadavkům zákazníka. I přesto je důležité znát ideální podobu vývojového procesu, aby bylo možné mít před sebou nějaký cíl. Tato kapitola se věnuje tomu, proč software nemůže být nikdy dokonalý.
1.2.1. Axiomy testování Zde uvedené axiomy neboli jisté známé pravdy, je nutné brát tak, že jejich znalost umožňuje zlepšit celkový náhled na procesy vývoje softwaru. 3
Žádný program není možné otestovat kompletně Je naivní si myslet, že lze každý softwarový produkt úplně otestovat. Důvody jsou tyto: • • • •
Počet možných vstupů je příliš velký. Počet možných výstupů je příliš velký. Počet možných cest, které vedou skrze software je příliš velký. Specifikace softwaru je subjektivní.
Když se vynásobí všechny tyto „příliš velký“, tak se dostane „příliš příliš mnoho“ testovacích případů. Takové množství testovacích případů se nedá vykonat v reálném čase ani na tom nejrychlejším superpočítači. Existují však metody, jak počet testovacích případů výrazně snížit, jak bude uvedeno dále.
Testování softwaru je postaveno na riziku Jestliže se nevykonají všechny možné testovací případy, podstupuje se v takovém testování jisté riziko. Aby riziko bylo co možná nejmenší, je zapotřebí vědět, jak zúžit obrovské množství testovacích případů na únosnou míru. Jednou takovou metodou využítí tzv. oblastí ekvivalence. Jedná se velmi jednoduchý princip. Odhadne se, které oblasti proměnných se vykonávají stejnými instrukcemi, jinak řečeno stejnou cestou. Potom stačí za tuto oblast vybrat jen několik málo reprezentantů pro vykonání testovacích případů.
Testování nikdy nemůže prokázat, že chyby neexistují Tento axiom vyplývá z prvního axiomu. Není totéž možné projít úplně všechny cesty programem nebo aktivovat všechny logické výrazy v podmínkách, protože to znamenalo kompletní testování. Může se provádět jakékoliv množství testu, nalézat a oznamovat chyby, ale v žádném případě nelze zaručit, že již žadné další chyby se nenaleznou.
Čím více chyb se najde, tím více chyb v softwaru je Tento jev může mít tyto příčiny: • Programátoři mají špatné dny • Programátoři dělají často stejné chyby • Některé chyby jsou skutečně pouhou špičkou ledovce Platí i opačné tvrzení k tomuto axiomu „z chyb vyplývají další chyby“. Pokud se žádná chyba nenalezne, ani při snačném úsilí, může být program skutečně napsán bez chyby.
Paradox pesticidů V roce 1990 vymyslel Boris Neizer ve druhém vydání knihy Software Testing Techniques pojem „paradox pesticidu“, kterým popsal skutečnost, že čím více určitý software testujeme, tím více se stává vůči testování imunním. Totéž funguje i u živého hmyzu a pesticidů. 4
K tomu jevu dochází, když se každá nová verze softwaru zkouší stejnými testy. Po několika iteracích se další chyby neodhalí. Jako obrana proti tomuto jevu je nutné neustále připravovat nové testy pro každou další verzi softwaru.
Ne všechny nalezené chyby se opraví K neopravení chyby může být několik důvodů: • Není na to dost času. • Ve skutečnosti to není chyba. • Oprava by byla příliš riskatní. • Oprava jednoduše nestojí za to. Do procesu rozhodování o chybě jsou obvykle zaposjeni softwaroví testeři, vedoucí projektu a programátoři. Každý z nich má na chyby poněkud jiný náhled a má svoje vlastní informace a názory na to, jestli se chyby mají nebo nemají opravit a proč.
Je těžké říci, že chyba je chybou Někdy se může stát, že chybu neobjeví ani testeří, ani programátoři a ani uživatelé. Jedná se tedy o chybu? Na to se dá odpovědět tím, že se daný produkt posoudí podle definice co je to chyba, která je uvedena 1.1.2 Mnohdy se stává, že jednen uživatel prohlásí o daném softwaru, že je plný chyb, zatímco druhý je s daným softwarem velmi spokojen a nehlásí žádné potíže. Důvodem je způsob používání daného softwaru.
Specifikace produktu nejsou nikdy konečné Říká se, že jedinou jistotou co v každém softwarovém projektu nastane, je že se požadavky změní. Proč tomu tak je? Především proto, že jak se postupuje projektem, seznamuje se se specifikací více lidí a ti začnou specifikaci upřesňovat, každý ze svého pohledu. Nejsou to jenom programátoři, ale i zadavatelé a případní budoucí uživatelé. Jakmile produkt začne být alespoň trochu provozuschopný, začnou vyplouvat na povrch věci na které se při počáteční tvorbě specifikace zapomělo, nedomyslelo nebo ještě v té době nebyly známy. Protože rychlost uvádění aplikací na trh je v současné době značná, dochází například k tomu, že konkureční produkty obsahují nové funkčnosti, které by se hodily i do námi vyvíjeného softwaru. Když se v takovém případě bude tým držet původní specifikace, dodá na trh zastaralý produkt. Lepší je zvolit druho cestu a to tedy doplnit specifikaci.
Testeři nejsou těmi nejoblíbenějšími členy projektového týmu To vyplývá přímo z cíle softwarovhého testera:„ Cílem softwarového testera je vyhledávat chyby, vyhledávat je co nejdříve a zajistit jejich nápravu“. Úkolem softwarového testera je kontrolovat a kritizovat práci svých kolegů, vyhledávat v ní problémy a ještě je zveřejňovat, to opravdu na popularitě opravdu nepřidá. 5
Testování softwaru je přesná technická disciplína Kdysí bývalo testování jen jakousi popelkou, na kterou zbýval čas až na konci projektu. Tehdy produkty byly malé a nebyly příliš komplikované. Dále ze softwarem pracoval velmi omezený počet lidí. Chyby tenkrát neznamenaly podstatný problém. Jestliže někdo pracoval jako softwarový tester, pak velmi často nebyl nijak zvlášť školený a k projektu se dostal na poslední chvíli, aby se v něm nějak povrtal a zkusil něco najít. Tyto časy jsou však pryč.
1.2.2. Pojmy z testování softwaru a jejich definice Pro pochopení základních principů, které se týkají vývoje softwaru a jeho testování, je zapatřebí se seznámit s příslušnými pojmy.
Přesnost a správnost Je nutné si uvědomit rozdíl v těchto dvou pojmech. Přesnost Správnost
Přesností rozumíme, zda výsledky jsou na požadované rozlišovací úrovni. Například u čísel, to je počet desetiných míst. Správností rozumíme, že výsledky odpovídají specifikaci. Například, že výpočet daně z přidané hodnoty odpovídá platnému zákonu.
Dané softwarový produkt se může potom ohodnotit čtyřmi možnými kombinacemi: 1. Ani přesný, ani správný Výpočet dan je nedostatečně přesný a podle neplatného zákona. 2. Přesný, ale ne správný Vyhovující přesnost výpočtu daně, ale podle neplatného zákona. 3. Správný, ale ne přesný Výpočet daně podle platného zákona, ale v nedostatečné přesnosti. 4. Přesný i správný Výpočet daně je přesný a podle platného zákona.
Verifikace a validace Pojmy verifikace a validace se velice často zaměňují. Verifikace
Validace
Verifikace představuje proces, jehož cílem je potvrdit, že něco - v našem případě softwérový produkt - vyhovuje zadané specifikaci. Při validaci se kontroluje, jestli softwérový produkt vyhovuje požadavkům uživatele.
Na první pohled obě definice jsou velice podobné, ale je ten rozdíl je v tom, že specifikace nemusí přesně se shodovat z požadavky uživatele. Příkladem může být Hubbleův dalekohled. Jeho zrcadlo bylo vyrobeno přesně, ale podle špatných
6
specifikacích. Testování zrcadla bylo v pozemských podmínkách vynecháno a na to je to špatně se přišlo až na oběžné dráze. Dalekohled nebylo možné přesně zaostřit a k opravě se mohlo přikročit až při servisním letu raketoplánu, kdy se vložila do optické cesty korekční čočka. Náklady na takovou opravu byly astronomické.
Kvalita a spolehlivost Často se tyto dva pojmy považují za shodné, ale není tomu tak. Kvalita Spolehlivost
Kvalita je něco jako stupeň dokonalosti. Spolehlivý softwérový produkt se vyznačuje stabilitou a důvěryhodností. Splehlivost je jen jedním z mnoha aspektů kvality
Pokud tester softwaru má zajistit vysokou kvalitu i spolehlivost programu zároveň, musí během celého procesu vývoje produktu provádět jak odpovídající verifikacim, tak i validaci.
Testování a zajišťování kvality Testování Zajišťování kvality (quality assurance - QA)
Při testování je cílem vyhledávat chyby, vyhledat je co nejdříve a zajistit jejich nápravu Hlavní úkolem osoby, odpovědné za zajišťování kvality softwaru, je vytvoření a prosazení vhodných standardů a metod, které zdokonalí proces vývoje a zabrání vzniku chyb.
1.2.3. Průběh testu Test lze rozdělit na tyto etapy: 1. 2. 3. 4. 5.
Plánování Příprava Provedení Vyhodnocení Rozbor chyb
Plánování Jde o plánování testu jednoho konkrétního předmětu testu. Předmětem může být třída, modul, komponenta, knihovna, program, systém. Účel plánu je určit cíl a prostředky na provedení testů. Činnosti plánování: 1. 2. 3. 4.
stanovit druh testu určit do jaké hloubky se bude testovat přidělit zdroje: finanční, technické, personální určit termíny 7
Výsledkem plánování je test, který se zahrne do plánu projektu.
Příprava testu Účelem je vytvořit podmínky pro ekonomické provedení testu. Činnosti přípravy: 1. 2. 3. 4. 5.
vybrat testovací případy specifikovat testovací přípravy specifikovat „postroj“ na testování realizovat „postroj“ testování určit postup na provedení testu
Výsledkem jsou: 1. předpis testu 2. postroj na testování
Komentář Pod pojmem postroj (anglicky harness) se rozumí v testování tzv. pohony a náhrady. Pohonem (test driver) se rozumí takové prostředky, které uvedou do činnosti testovaný předmět a náhrady (test stubs) jsou takové prostředky, které suplují nedokončené prostředky, které vyžaduje testovaný předmět. Součástí postroje jsou též testovací data.
Výběr testovacích případů Cílem je s minimálním počtem testovacích pravděpodobností nalézt co možná nejvíce chyb.
případů
s
maximální
Testování je vždy založeno na metodě náhodné kontroly (viz předchozí kapitoly) • • • •
Testovací případ je vzorkem jako ověřit činnost testovaného předmětu. Výběr testovacích vzorků může být: náhodný systematický
Zdroje informací pro výběr testovacích případů: • • • • • •
předcházející testy specifikace produktu uživatelská dokumentace návrh programu normy, zákony zkušenost
Specifikace testovacích případů Pro každý testovací případ je nutné stanovit: 8
• • • • •
jednoznačné označení předpoklady / počáteční podmínky vstupní data instrukce očekávané reakce na výstupech
Určení postupu na provedení testu
1.3. Jednotkové testy - JUnit 1.3.1. Úvod JUnit jsou výkonným nástrojem vývojových technik řízení vývoje softwaru testy (test-driven development) a "Extrémního programování". JUnit byl později portován na mnoho dalších jazyků, např. C# (NUnit), Python (PyUnit), Fortran (fUnit), Perl (Test::Class a Test::Unit) a C++ (CPPUnit). Tato rodina frameworků pro jednotkové testy byla pojmenována xUnit. Převzato z http://cs.wikipedia.org/wiki/Unit_testing: Slovní spojení unit testing se při programování používá jako pojem a v českém jazyce pravděpodobně dosud nemá ustálený překlad. Pojem by se dal přeložit jako testování jednotek, testování aplikačních jednotek, doslovně jako jednotkové testování. Unit testing je činností související s vývojem aplikačních programů. Koncoví uživatelé programů se s ním nesetkávají. Pod pojem unit testing se zahrnují nástroje, metodika a činnost, jejímž cílem je ověřování správné funkčnosti dílčích částí neboli jednotek zdrojového textu. Technicky řečeno, za jednotku by se měla považovat samostatně testovatelná část aplikačního programu. Z pohledu procedurálního programování může být jednotkou program, funkce, procedura, atd. Z pohledu objektově orientovaného programování je jednotkou obvykle třída. V rámci ní se ale obvykle individuálně testují její metody (tj. členské funkce). Jednotkový test je test pro určitou jednotku. V ideálním případě by měl být každý testovaný případ nezávislý na ostatních. Při testování se snažíme testovanou část izolovat od ostatních částí programu. Za tím účelem se někdy vytvářejí pomocné objekty, které simulují předpokládaný kontext, ve kterém testovaná část pracuje (mock object). Technika unit testing je jednou z klíčových součástí metodiky, která se nazývá extrémní programování.
1.3.2. Ukázka použití JUnit Výpis 1.1. Testovaná třída Koule se dvěmi chybami class Koule { static final double mojePI = 3.14; private double polomer; 9
public double objem() { return (4 / 3) * mojePi * polomer; } public void setPolomer(double polomer) { this.polomer = polomer; }
}
public double getPolomer() { return polomer; } Tato konstanta, která má nedostatečnou přesnost. Chybný vzorec výpočtu objemu koule. Výpis 1.2. Testovací třída KouleTest pro třídu Koule
package Koule; import org.junit.Test; import static org.junit.Assert.*; public class KouleTest { final double r = 10.0; Koule koule; public KouleTest() { koule = new Koule(); koule.setPolomer(r); } @Test public void testObjem( ) { koule.setPolomer(r); double result = koule.objem(); double expResult = (4.0 / 3.0) * Math.PI * Math.pow(r, 3); assertEquals(expResult, result, 0.1); } @Test public void testSetPolomer() { koule.setPolomer(2 * r); double result = koule.getPolomer(); double expResult = 2 * r; assertEquals(expResult, result, 0.1); } @Test 10
}
public void testGetPolomer() { Koule k = new Koule(); k.setPolomer(2 * r); double result = k.getPolomer(); double expResult = 2 * r; assertEquals(expResult, result, 0.1); } Importování potřebných knihoven JUnit. Signatura testovací třídy KouleTest. Je zvykem testovací třídu pojmenovat stejně jako testovanou třídu a přidat příponu Test. Deklaraci každé testovací metody musí předcházet anotace @Test. Potom je tato metoda automaticky aktivována při spuštění testovacího módu, aniž by bylo ji potřeba nějak explicitně vyvolat. Jméno testovací metody již může být zcela obecné. Při automatickém vygenerování kostry testovací třídy podle testované třídy, se ke každé veřejné metodě vygeneruje do testovací třídy testovací metoda s názvem, který se skládá ze slova test a názvu testované metody. V samostné testovací metodě je zapotřebí očekávaným způsobem změnit stav testovaného objektu. Testovaný objekt lze vytvořit například v konstruktoru v testovací třídě, jako v tomto případě, nebo jej lze vytvořit lokálně přímo v testovací metodě. Pokud se objekt vytvoří pouze v testovací metodě, je samozřejmě po ukončení metody ztracen a další testovací metoda si musí vytvořit nový a nastavit do svého očekávaného stavu. Při využití jednoho testovaného objektu pro více testovacích metod je nutné počítat s tím, že testovací metody nemusí být spuštěny v očekávaném pořadí tak, jak jsou seřazeny v testovací třídě. Po změně stavu objektu je nutné v testovací metodě získat potvrzení této změny, která je přístupná přes veřejné metody testovaného objektu. Po změně stavu objektu je nutné v testovací metodě nastavit očekávaný výsledek změny stavu objektu. Příkaz, respektive metoda, AssertEquals provede porovnání očekávaného stavu se zjištěný stavem objektu. Při neshodě, dojde o tomto zjištění k výpisu. Toto jsou další testovací metody. Vzhledem k tomu, že obě tyto metody používají stejné metody testovaného objektu, bylo by možné jednu z nich zrušit a zbylou vhodně přejmenovat.
11