Professional Documents
Culture Documents
Szoftver Tesztelés
Szoftver Tesztelés
Készítették:
Ficsor Lajos (4,5,7 fejezet)
Dr. Kovács László (1, 10 fejezet)
Krizsán Zoltán (8, 11 fejezet)
Dr. Kusper Gábor (1, 2, 3, 6, 9 fejezet)
Tartalomjegyzék
1 A tesztelés alapjai
3 Statikus technikák
5 Integrációs teszt
6 Biztonsági tesztelés
7 Tesztmenedzsment
8 Eszköztámogatás a tesztelésben
9 Hibakövető rendszerek
10 Adatbázisok tesztelése
11 Esettanulmány
1 A tesztelés alapfogalmai
Tesztelésre azért van szükség, hogy a szoftver termékben meglévő hibákat még az üzembe
helyezés előtt megtaláljuk, ezzel növeljük a termék minőségét, megbízhatóságát. Abban szinte
biztosak lehetünk, hogy a szoftverben van hiba, hiszen azt emberek fejlesztik és az emberek
hibáznak. Gondoljunk arra, hogy a legegyszerűbb programban, mondjuk egy szöveges menü
kezelésben, mennyi hibát kellett kijavítani, mielőtt működőképes lett. Tehát abban szinte biztosak
lehetünk, hogy tesztelés előtt van hiba, abban viszont nem lehetünk biztosak, hogy tesztelés után
nem marad hiba. A tesztelés után azt tudjuk elmondani, hogy a letesztelt részekben nincs hiba, így
nő a program megbízhatósága. Ez azt is mutatja, hogy a program azon funkcióit kell tesztelni,
amiket a felhasználók legtöbbször fognak használni.
1. A tesztelés hibák jelenlétét jelzi: A tesztelés képes felfedni a hibákat, de azt nem, hogy
nincs hiba. Ugyanakkor a szoftver minőségét és megbízhatóságát növeli.
2. Nem lehetséges kimerítő teszt: Minden bemeneti kombinációt nem lehet letesztelni (csak
egy 10 hosszú karakterláncnak 256^10 lehetséges értéke van) és nem is érdemes.
Általában csak a magas kockázatú és magas prioritású részeket teszteljük.
3. Korai teszt: Érdemes a tesztelést az életciklus minél korábbi szakaszában elkezdeni, mert
minél hamar találunk meg egy hibát (mondjuk a specifikációban), annál olcsóbb javítani. Ez
azt is jelenti, hogy nemcsak programot, hanem dokumentumokat is lehet tesztelni.
4. Hibák csoportosulása: A tesztelésre csak véges időnk van, ezért a tesztelést azokra a
modulokra kell koncentrálni, ahol a hibák a legvalószínűbbek, illetve azokra a bemenetekre
kell tesztelnünk, amelyre valószínűleg hibás a szoftver (pl. szélsőértékek).
7. A hibátlan rendszer téveszméje: Hiába javítjuk ki a hibákat a szoftverben, azzal nem lesz
elégedett a megrendelő, ha nem felel meg az igényeinek. Azaz használhatatlan szoftvert
nem érdemes tesztelni.
1-1
• Feketedobozos (black-box) vagy specifikáció alapú, amikor a specifikáció alapján készülnek
a tesztesetek.
A fehérdobozos tesztelést strukturális tesztelésnek is nevezzük, mert mindig egy már kész
struktúrát, pl. program kódot, tesztelünk. A strukturális teszt esetén értelmezhető a (struktúra)
lefedettség. A lefedettség azt mutatja meg, hogy a struktúra hány százalékát tudjuk tesztelni a
meglévő tesztesetekkel. Általában ezeket a struktúrákat teszteljük:
• kódsorok,
• elágazások,
• metódusok,
• osztályok,
• funkciók,
• modulok.
• komponensteszt,
• integrációs teszt,
• rendszerteszt,
• átvételi teszt.
1-2
hívjuk, mert ezeket a fejlesztő cég alkalmazottai vagy megbízottjai végzik. Az átvételi teszt során a
felhasználók a kész rendszert tesztelik. Ezek általában időrendben is így követik egymást.
• unit-teszt,
• modulteszt.
A unit-teszt, vagy más néven egységteszt, a metódusokat teszteli. Adott paraméterekre ismerjük a
metódus visszatérési értékét (vagy mellékhatását). A unit-teszt megvizsgálja, hogy a tényleges
visszatérési érték megegyezik-e az elvárttal. Ha igen, sikeres a teszt, egyébként sikertelen. Elvárás,
hogy magának a unit-tesztnek ne legyen mellékhatása.
A modulteszt általában a modul nem-funkcionális tulajdonságát teszteli, pl. sebességét, vagy, hogy
van-e memóriaszivárgás (memory lake), van-e szűk keresztmetszet (bottleneck).
Az integrációs teszt az összeillesztés során keletkező hibákat keresi. Mivel a részeket más-más
programozók, csapatok fejlesztették, ezért az elégtelen kommunikációból súlyos hibák
keletkezhetnek. Gyakori hiba, hogy az egyik programozó valamit feltételez (pl. a metódus csak
pozitív számokat kap a paraméterében), amiről a másik nem tud (és meghívja a metódust egy
negatív értékkel). Ezek a hibák kontraktus alapú tervezéssel (design by contract) elkerülhetőek.
Az integrációs teszteket érdemes minél hamarabb elvégezni, mert minél nagyobb az integráció
mértéke, annál nehezebb meghatározni, hogy a fellelt hiba (általában egy futási hiba) honnan
származik. Ellenkező esetben, azaz amikor már minden komponens kész és csak akkor tesztelünk,
akkor ezt a „nagy bumm tesztnek” (big bang tesztnek) nevezzük, ami rendkívül kockázatos.
• a követelmény specifikációnak,
1-3
• a funkcionális specifikációnak,
• a rendszertervnek.
A rendszerteszt nagyon gyakran feketedobozos teszt. Gyakran nem is a fejlesztő cég, ahol esetleg
elfogultak a tesztelők, hanem egy független cég végzi. Ilyenkor a tesztelők és a fejlesztők közti
kapcsolat tartást egy hibabejelentő (bug trucking) rendszer látja el. A rendszerteszt feladata, hogy
ellenőrizze, hogy a specifikációknak megfelel-e a termék. Ha pl. a követelmény specifikáció azt írja,
hogy lehessen jelentést készíteni az éve forgalomról, akkor ezt a tesztelők kipróbálják, hogy lehet-
e, és hogy helyes-e a jelentés. Ha hibát találnak, azt felviszik a hibabejelentő rendszerbe.
• alfa teszt,
• béta teszt,
Az alfa teszt a kész termék tesztje a fejlesztő cégnél, de nem a fejlesztő csapat által. Ennek része,
amikor egy kis segédprogram több millió véletlen egérkattintással ellenőrzi, hogy össze-vissza
kattintgatva sem lehet kifektetni a programot.
Ezután következik a béta teszt. A béta tesztet a végfelhasználók egy szűk csoportja végzi.
Játékoknál gyakori, hogy a kiadás előtt néhány fanatikus játékosnak elküldik a játékot, akik rövid
alatt sokat játszanak vele. Cserébe csak azt kérik, hogy a felfedezett hibákat jelentsék.
Ezután jön egy sokkal szélesebb béta teszt, amit felhasználói átvételi tesztnek nevezünk. Ekkor már
az összes, vagy majdnem az összes felhasználó, megkapja a szoftvert és az éles környezetben
használatba veszi. Azaz installálják és használják, de még nem a termelésben. Ennek a tesztnek a
célja, hogy a felhasználók meggyőződjenek, hogy a termék biztonságosan használható lesz majd
éles körülmények között is. Itt már elvárt, hogy a fő funkciók mind működjenek, de előfordulhat,
hogy az éles színhelyen előjön olyan környezet függő hiba, ami a teszt környezetben nem jött elő.
Lehet ez pl. egy funkció lassúsága.
Ezután már csak az üzemeltetői átvételi teszt van hátra. Ekkor a rendszergazdák ellenőrzik, hogy a
biztonsági funkciók, pl. a biztonsági mentés és a helyreállítás, helyesen működnek-e.
1-4
• tesztterv elkészítése,
• tesztesetek tervezése,
• felkészülés a végrehajtásra,
• tesztek végrehajtása,
• eredmények értékelése,
• jelentéskészítés.
A tesztterv fontos dokumentum, amely leírja, hogy mit, milyen céllal, hogyan kell tesztelni. A
tesztterv általában a rendszerterv része, azon belül is a minőségbiztosítás (quality assurance, QA)
fejezethez tartozik. A teszt célja lehet:
• megtalálni a hibákat,
• növelni a megbízhatóságot,
• megelőzni a hibákat.
A fejlesztői tesztek célja általában minél több hiba megtalálása. Az átvételi teszt célja, hogy a
felhasználók bizalma nőjön a megbízhatóságban. A regressziós teszt célja, hogy megelőzni, hogy a
változások a rendszer többi részében hibákat okozzanak.
A tesztterv elkészítéséhez a célon túl tudni kell, hogy mit és hogyan kell tesztelni, mikor tekintjük a
tesztet sikeresnek. Ehhez ismernünk kell a következő fogalmakat:
• A teszt tárgya: A rendszer azon része, amelyet tesztelünk. ez lehet az egész rendszer is.
• Tesztadat: Olyan adat, amivel meghívjuk a teszt tárgyát. Általában ismert, hogy milyen
értéket kellene erre adnia a teszt tárgyának vagy milyen viselkedést kellene produkálnia. Ez
az elvárt visszatérési érték, illetve viselkedés. A valós visszatérési értéket, illetve viselkedést
hasonlítjuk össze az elvárttal.
• Kilépési feltétel: Minden tesztnél előre meghatározzuk, mikor tekintjük ezt a tesztet
lezárhatónak. Ezt nevezzük kilépési feltételnek. A kilépési feltétel általában az, hogy
minden tesztest sikeresen lefut, de lehet az is, hogy a kritikus részek tesztlefedettsége
100%.
A tesztterv leírja a teszt tárgyát, kigyűjti a tesztbázisból a teszt által lefedett követelményeket,
meghatározza a kilépési feltételt. A tesztadatokat általában csak a teszteset határozzák meg, de
gyakran a tesztesetek is részei a teszttervnek.
1-5
A tesztesetek leírják, hogy milyen tesztadattal kell meghajtani a teszt tárgyát. Illetve, hogy mi az
elvárt visszatérési érték vagy viselkedés. A tesztadatok meghatározásához általában úgynevezett
ekvivalencia-osztályokat állítunk fel. Egy ekvivalencia-osztály minden elemére a szoftver
ugyanazon része fut le. Természetesen más módszerek is léteznek, amikre később térünk ki.
A tesztek végrehajtása során teszt naplót vezetünk. Ebbe írjuk le, hogy milyen lépéseket hajtottunk
végre és milyen eredményeket kaptunk. A tesz napló alapján a tesztnek megismételhetőnek kell
lennie. Ha hibát találunk, akkor a hibabejelentőt a teszt napló alapján töltjük ki.
A tesztek után meg kell vizsgálni, hogy sikeresen teljesítettük-e a kilépési feltételt. Ehhez a
tesztesetben leírt elvárt eredményt hasonlítjuk össze a teszt naplóban lévő valós eredménnyel a
kilépési feltétel alapján. Ha kilépési feltételek teljesülnek, akkor mehetünk tovább. Ha nem, akkor
vagy a teszt tárgya, vagy a kilépési feltétel hibás. Ha kell, akkor módosítjuk a kilépési feltételt. Ha
teszt tárgya hibás, akkor a hibabejelentő rendszeren keresztül értesítjük a fejlesztőket. A teszteket
addig ismételjük, míg mindegyik kilépési feltétele igaz nem lesz.
Végül jelentést kell készítenünk. Itt arra kell figyelnünk, hogy sok programozó kritikaként éli meg,
ha a kódjában a tesztelők hibát találnak. Úgy érzi, hogy rossz programozó és veszélyben van az
állása. Ezért a tesztelőket nem várt támadások érhetik. Ennek elkerülésére a jelentésben nem
szabad személyeskedni, nem muszáj látnia főnöknek, kinek a kódjában volt hiba. A hibákat rá lehet
fogni a rövid időre, a nagy nyomásra. Jó, ha kiemeljük a tesztelők és a fejlesztők közös célját, a
magas minőségű, hibamentes szoftver fejlesztését.
1-6
1.5.1 A forráskód szintaktikai ellenőrzése
Az formális nyelvek mondatok szavakból, jelekből történő felépítését írják le. Formálisan a formális
nyelv egy párossal írható le, melyben adott az alapjelek halmaza és a képezhető, elfogadott
mondatok halmaza. A mondatok halmaza az összes képezhető véges jelsorozatok halmazának
részhalmazaként értelmezhető.
Σ: jelek halmaza
L ⊆ Σ* : nyelv
A nyelvek esetében egy nyelvtan írja le a jelhalmazból képzett és a nyelv által elfogadott mondatok
halmazát. A nyelvtan leírja a mondatok képzési szabályait. A szabályok alapvetően
A→B
G = (T, N, R, S)
ahol
• R: szabályok halmaza
1-7
• reguláris nyelvek: a szabályok A → aB alakúak;
A programozási nyelvek alapvetően a reguláris nyelvek osztályába tartoznak. Egy SQL DELETE
parancs esetében például az alábbi szabályokat kell alkalmazni, ahol a példában egy –egy szót is
atomi szimbólumnak tekintünk.
S = delete R
R = from Q
Q = ?tabla P
Q = ?tabla
P = where O
O = ?feltétel
A mintában a ? jel mögött egy újabb egység van, melyhez önálló saját értelmezési nyelvtan
tartozik.
• állapot átmeneteket
• eseményeket
1-8
• induláskor egy induló állapotban van a rendszer
• egy esemény bekövetkezésekor állapot átmenet valósul meg: az aktuális állapotból azon
átmeneten megy tovább, melyhez a bejövő esemény tartozik
• az automata egy végállapot elérésekor áll le
A szintaktika ellenőrzéskor a végállapot lehet egy elfogadó vagy egy elvető (hiba) állapot.
• véges automata
• determinisztikus automata
• fuzzy automata
Az előzőekben ismertetett reguláris nyelvek megvalósíthatók véges automatákkal így az
értelmezés folyamata egy automatával végrehajtható. Az automata működési modellje egy
táblázattal foglalható össze, melyben az alábbi oszlopok szerepelnek:
• induló állapot
• esemény
• célállapot
Az esemény a forráskód elemzésénél a soron következő beolvasott jelet (szót) jelöli. A DELETE
parancs setében az alábbi táblázat alapján működhet az értelmező:
S delete R
S * Hiba!
R from Q
R * Hiba!
Q ?tábla P
Q * Hiba!
P # OK!
P where O
P * Hiba!
O ?feltétel OK!
O * Hiba!
1-9
A táblázatban * jel jelöli az egyéb eseményeket és # jel a mondat vége eseménynek felel meg.
• modul (rutin)
• szekvencia
• elágazás
• ciklus
• szekvenciát,
• elágazást,
• ciklust.
• skalár
• tömb
• halmaz
1-10
• rekord
• fa
A hierarchia reprezentáció a program statikus szerkezeté írja le, a program azonban egy
végrehajtási szerkezet ad meg. A program hagyományos végrehajtása során mindig van egy
kitüntetett utasítás, mely végrehajtás alatt áll. Ez az aktuális utasítás vándorol a program futása
alatt. Egy adott utasításból egy vagy több más utasításba kerülhet át a vezérlés.
{P} s {Q}
P : precondition
s : source (forráskód)
Q: postcondition.
1-11
Természetesen a P és Q részek lehetnek mindig teljesülő kifejezések is. A Hoare formalizmus célja
a program részleges helyességének ellenőrzése, tehát annak bizonyítása, hogy ha P teljesül, akkor
az s végrehajtása után Q is teljesülni fog.
(p1,p2,p3,… ) → q
alakban lehet megadni és azt jelzi, hogy ha teljesülnek a p1,p2,p3 … logikai kifejezések, akkor a q
állítás is teljesül. A levezetési szabályok egy s program esetén az alábbi típusokat fedik le:
Mivel a Q levezetése a P-ből több lépésen keresztül történhet csak, a bizonyítás egy levezetési
fával írható le.
Példaként a feltételes utasításhoz tartozó szabályt véve, az implikáció a következő alakot ölti:
A feldolgozás egy további eleme a feltételek erősítése vagy gyengítése. A precondition erősítése
formalizmusa:
A fenti példákból is jól látható, hogy a Hoare formalizmus a helyesség ellenőrzését igen absztrakt
szinten végzi és igen körülményes és költséges a levezetési fa felépítése. Emiatt a módszert
napjainkban még csak kisebb méretű feladatoknál alkalmazzák és a gyakorlati rendszerekben
döntően a heurisztikus módszerek dominálnak.
1-12
Tartalomjegyzék
1 A tesztelés alapfogalmai .......................... ................................................... ..............................1-1
1.1 A tesztelés alapelvei ............................. ................................................... ...........................1-1
1.2 Tesztelési technikák.............................. ................................................... ...........................1-1
1.3 A tesztelés szintjei .............................. ................................................... .............................1-2
1.4 A tesztelési tevékenység ............................................................................. .......................1-4
1.5 A programkód formális modellje .................... ................................................... ................1-6
1.5.1 A forráskód szintaktikai ellenőrzése ................................................................. ..........1-7
1.5.2 Forráskód szemantikai ellenőrzése .................................................................... .......1-10
1-13
2 A tesztelés helye a szoftver életciklusában
Ebben a fejezetben röviden áttekintjük a szoftver életciklusát és az ezt meghatározó
legfontosabb módszertanokat. Külön kiemeljük a tesztelés helyét az életciklusban és a
módszertanokban is.
2.1 A szoftverkrízis
A tesztelés szükségességét, mint annyi mást, a szoftverkrízis (software crisis) húzta alá. A
szoftverkrízis alatt azt értjük, hogy a szoftver projektek jelentős része sikertelen. Sikertelen a
következő értelemben:
Az életciklus lépéseit a módszertanok határozzák meg. Ezeket később fejtjük ki. Itt egy
általános életciklust tekintünk át.
2-1
• A felhasználókban új igény merül fel.
• Implementáció (szoftver).
. ábra Életciklus
Látható, hogy az első lépés és az utolsó ugyanaz. Ez biztosítja a ciklikusságot. Elvileg egy
hasznos szoftvernek végtelen az életciklusa. Gyakorlatilag a szoftver és futási környezete
2-2
elöregszik. Előbb-utóbb már nem lesz programozó, aki ismerné a programozási nyelvet, amin
íródott (ilyen probléma van manapság a COBOL programokkal), a futtató operációs
rendszerhez nincsenek frissítések, a meghibásodott hardver elemeket nem lehet pótolni. Az
ilyen IT rendszereket hívjuk „legacy system”-nek (kiöregedett, hagyaték rendszernek).
Valahol itt van vége az életciklusnak. Az életciklus egyes lépéseit részletesebben is kifejtjük.
2.3 Módszertanok
A módszertanok feladata, hogy meghatározzák, hogy a szoftver életciklus egyes lépései
milyen sorrendben követik egymást, milyen dokumentumokat, szoftver termékeket kell
előállítani és hogyan. Egy nagy szabálykönyvre emlékeztetnek, ami pontosan leírja, hogyan
kell szoftvert „főzni”. Ha betartjuk a receptet, akkor egy átlagos minőségű szoftvert kapunk,
de az átlagos minőség garantált.
2.4 V-modell
A V-modell (angolul: V-Model vagy Vee Model) a nevét onnan kapta, hogy két szára van és
így egy V betűhöz hasonlít. Az egyik szára megegyezik a vízesés modellel. Ez a fejlesztési szár.
A másik szára a létrejövő termékek tesztjeit tartalmazza. Ez a tesztelési szár. Az egy szinten
lévő fejlesztési és tesztelési lépések összetartoznak, azaz a tesztelési lépés a fejlesztési lépés
során létrejött dokumentumokat használja, vagy a létrejött terméket teszteli. Ennek
megfelelően az előírt fejlesztési és tesztelési lépések a következők:
2-3
A V-modell a vízesés modell kiegészítése teszteléssel. Ez azt jelenti, hogy először végre kell
hajtani a fejlesztés lépéseit, ezután jönnek a tesztelés lépései. Ha valamelyik teszt hibát talál,
akkor vissza kell menni a megfelelő fejlesztési lépésre.
Ezután következik a funkcionális specifikáció elkészítése, amely leírja, hogyan kell majd
működnie a szoftvernek. Ez lesz a rendszerteszt alapja. Ha a funkcionális specifikáció azt írja,
2-4
hogy a „Vásárol gomb megnyomására ki kell írni a kosárban lévő áruk értékét”, akkor a
rendszertesztben lesz egy vagy több teszteset, amely ezt teszteli. Például, ha üres a kosár,
akkor az árnak nullának kell lennie.
Ezután következik a rendszerterv, amely leírja, hogy az egyes funkciókat hogyan, milyen
komponensekkel, osztályokkal, metódusokkal, adatbázissal fogjuk megvalósítani. Ez lesz a
komponens teszt egyik alapja. A rendszerterv leírja tovább, hogy a komponensek hogyan
működnek együtt. Ez lesz az integrációs teszt alapja.
Ha ezen sikeresen túl vagyunk, akkor az integrációs teszt következik a rendszerterv alapján.
Ha itt problémák merülnek fel, akkor visszamegyünk a V betű másik szárára a
rendszertervhez. Megnézzük, hogy a hiba a rendszertervben vagy az implementációban van-
e. Ha kell, megváltoztatjuk a rendszertervet, majd az implementációt is.
Ha a fejlesztés és tesztelés alatt nem változnak a követelmények, akkor ez egy nagyon jó,
kiforrott, támogatott módszertan. Ha valószínű a követelmények változása, akkor inkább
iteratív, vagy még inkább agilis módszert válasszunk.
2-5
Ez a megközelítés annyira sikeres volt, hogy a modern módszertanok majd mindegyike
prototípus alapú. Az iteratív módszerek általában minden mérföldkőhöz kötnek egy
prototípust. Az agilis módszertanok akár minden nap új (lásd napi fordítás) prototípust
állítanak elő.
2-6
A prototípus készítést akkor a legcélszerűbb használni, ha a rendszer és a felhasználó között
sok lesz a párbeszéd. A modell on-line rendszerek elemzésében és tervezésében nagyon
hatékony, különösen a tranzakció feldolgozásnál. Olyan rendszereknél, ahol kevés interakció
zajlik a rendszer és a felhasználó között, ott kevésbé éri meg a prototípus modell használata,
ilyenek például a számítás igényes feladatok. Különösen jól használható a felhasználói felület
kialakításánál.
2-7
Ezt a megközelítést több módszertan is alkalmazza, például a prototípus modell, a gyors
alkalmazásfejlesztés (RAD), a Rational Unified Process (RUP) és az agilis fejlesztési modellek.
Itt ezeknek a módszertanoknak a közös részét, az iterációt ismertetjük. Egy iteráció a
következő feladatokból áll:
• Követelményelemzés
• Elemzés és tervezés
• Implementáció
• Tesztelés
• Értékelés
2-8
Az iteratív modell fő ereje abban rejlik, hogy az életciklus lépései nem egymás után jönnek,
mint a strukturált módszertanok esetén, hanem időben átfedik egymást. Minden iterációban
van elemzés, tervezés, implementáció és tesztelés. Ezért, ha találunk egy félreértést, akkor
nem kell visszalépni, hanem néhány iteráció segítségével oldjuk fel a félreértést. Ez az jelenti,
hogy kevésbé tervezhető a fejlesztés ideje, de jól alkalmazkodik az igények változásához.
Mivel a fejlesztés lépéseit mindig ismételgetjük, ezért azt mondjuk, hogy ezek időben átfedik
egymást, hiszen minden szakaszban minden lépést végre kell hajtani. A kezdeti iterációkban
több az elemzés, a végéhez közeledve egyre több a tesztelés. Már a legelső szakaszban is van
tesztelés, de ekkor még csak a teszttervet készítjük. Már a legelső szakaszban is van
implementáció, de ekkor még csak az architektúra osztályait hozzuk létre. És így tovább.
A feladatot több iterációra bontjuk. Ezeket általában több kisebb csapat implementálja
egymással versengve. Aki gyorsabb, az választhat iterációt a meglévők közül. A választás nem
teljesen szabad, a legnagyobb prioritású feladatok közül kell választani. A prioritás
meghatározása különböző lehet, általában a leggyorsabban megvalósítható és legnagyobb
üzleti értékű, azaz a legnagyobb üzleti megtérüléssel (angolul: return of investment) bíró
feladat a legnagyobb prioritású.
Üzleti folyamatok elemzése: Első lépésben meg kell ismerni a megrendelő üzleti folyamatait.
Az üzleti folyamatok modellezése során fel kell állítani egy projekt fogalomtárat. A
lemodellezett üzleti folyamatokat egyeztetni kell a megrendelővel, hogy ellenőrizzük jól
értjük-e az üzleti logikát. Ezt üzleti elemzők végzik, akik a megrendelők és a fejlesztők fejével
is képesek gondolkozni.
2-9
megfelelnek-e a tervezők által kitalált tervezési és programozási irányelveknek. Ebben a
szakaszban a programozók unit-teszttel biztosítják a kód minőségét.
Tesztelés: A tesztelési szakaszban különböző tesztelési eseteket találunk ki, ezeket unit-
tesztként valósítjuk meg. Itt vizsgáljuk meg, hogy az elkészült kód képes-e együttműködni a
program többi részével, azaz integrációs tesztet hajtunk végre. Regressziós tesztek
segítségével ellenőrizzük, hogy ami eddig kész volt, az nem romlott el. Ehhez lefuttatjuk az
összes unit-tesztet. Rendszerteszt csak a késői tesztelési fázisokban van.
Értékelés: A fejlesztés minden ciklusában el kell dönteni, hogy az elkészült verziót elfogadjuk-
e, vagy sem. Ha nem, akkor újra indul ez az iteráció. Ha igen, vége ennek az iterációnak. Az
így elkészült kódot feltöltjük a verziókövető rendszerbe, hogy a többi csapat is hozzáférjen.
Az értékelés magában foglal egy átvételi tesztet is. Ha a megrendelő nem áll rendelkezésre,
akkor általában a csoportok munkáját összefogó vezető programozó / tervező helyettesíti.
Amennyiben a folyamat során elértünk egy mérföldkőhöz, akkor általában át kell adnunk egy
köztes prototípust is. Ekkor mindig rendelkezésre áll a megrendelő, hogy elvégezzük a
felhasználói átvételi tesztet.
Végül vagy elérjük azt a pontot, ahol azt mondjuk, hogy ez így nem elkészíthető, vagy azt
mondjuk, hogy minden felmerült igényt kielégít a szoftverünk és szállíthatjuk a
megrendelőnek.
2-10
• Komponensek újrahasznosítása.
A gyorsaság eléréséhez sok meglévő komponenst kell felhasználni, amit a csapatnak jól kell
ismernie. A komponensek lehetnek saját fejlesztésűek vagy megvásároltak. Komponenst
vásárolni nagy kockázat, mert ha hiba van benne, azt nem tudjuk javítani, ha nem kapjuk
meg a forrást, de még úgy is nagyon nehéz. Ezért a komponens gyártók nagyon alaposan
tesztelik terméküket.
2-11
melyekből adat objektumokat hozunk létre. Beazonosítjuk az attribútumokat és a
kapcsolatokat az adatok között.
Hátránya, hogy magasan képzett fejlesztőkre van szükség, emellett fontos a fejlesztők és a
végfelhasználók elkötelezettsége a sikeres szoftver iránt. Ha a projekt nehezen bontható fel
modulokra, akkor nem a legjobb választás a RAD. Nagyobb rendszerek fejlesztése ezzel a
módszertannal kockázatos.
2-12
Az agilis szoftverfejlesztés alapelvei:
Az agilis szoftverfejlesztésnek nagyon sok fajtája van. Ebben a jegyzetben csak ezt a kettőt
tárgyaljuk:
• Scrum
• Kevesebb dokumentáció.
2-13
a termékhez, ezeket egytől négy hétig terjedő ciklusokban (más néven keretekben vagy
idődobozokban) készítik el, és ezek a ciklusok ismétlődnek. Ezáltal nincs olyan jellegű
részletes hosszú távú tervezés, mint például a vízeséses modellnél, csak az a minimális, amire
az adott ciklusban szükség van. Ez abból az elvből indul ki, hogy nem lehet előre tökéletesen,
minden részletre kiterjedően megtervezni egy szoftvert, mert vagy a tervben lesz hiba, vagy
a megrendelő változtat valamit.
Az agilis módszertanok nagyon jól működnek, amíg a feladatot egy közepes méretű (5-9 fős)
csapat képes megoldani. Nagyobb csoportok esetén nehéz a csapat szellem kialakítása. Ha
több csoport dolgozik ugyanazon a célon, akkor köztük a kommunikáció nehézkes. Ha
megrendelő nem hajlandó egy elkötelezett munkatársát a fejlesztő csapat rendelkezésére
bocsátani, akkor az kiváltható egy üzleti elemzővel, aki átlátja a megrendelő üzleti
folyamatait, de ez kockázatos.
2.4.5 Scrum
A Scrum egy agilis szoftverfejlesztési metódus. Jellegzetessége, hogy fogalmait az amerikai
futballból, más néven rugby, meríti. Ilyen fogalom, maga a Scrum is, amely dulakodást jelent.
A módszertan jelentős szerepet tulajdonít a csoporton belüli összetartásnak. A csoporton
2-14
belül sok a találkozó, a kommunikáció, lehetőség van a gondok megbeszélésre is. Az ajánlás
szerint jó, ha a csapat egy helyen dolgozik és szóban kommunikál.
A Scrum által előírt fejlesztési folyamat röviden így foglalható össze: A Product Owner
létrehoz egy Product Backlog-ot, amelyre a teendőket felhasználói sztoriként veszi fel. A
sztorikat prioritással kell ellátni és megmondani, mi az üzleti értékük. Ez a Product Owner
feladata. A Sprint Planning Meetingen a csapat tagjai megbeszélik, hogy mely sztorik
megvalósítását vállalják el, lehetőleg a legnagyobb prioritásúakat. Ehhez a sztorikat kisebb
feladatokra bontják, hogy megbecsülhessék mennyi ideig tart megvalósítani azokat. Ezután
jön a sprint, ami 2-4 hétig tart. A sprint időtartamát az elején fixálja a csapat, ettől eltérni
nem lehet. Ha nem sikerül befejezni az adott időtartam alatt, akkor sikertelen a sprint, ami
büntetést, általában prémium megvonást, von maga után. A sprinten belül a csapat és a
Scrum Master naponta megbeszélik a történteket a Daily Meetingen. Itt mindenki elmondja,
hogy mit csinált, mi lesz a következő feladata, és milyen akadályokba (impediment) ütközött.
A sprint végén következik a Sprint Review, ahol a csapat bemutatja a sprint alatt elkészült
sztorikat. Ezeket vagy elfogadják, vagy nem. Majd a Sprint Retrospective találkozó
következik, ahol a Sprint során felmerült problémákat tárgyalja át a csapat. A megoldásra
konkrét javaslatokat kell tenni. Ezek után újra a Sprint Planning Meeting következik. A
fejlesztett termék az előtt piacra kerülhet, hogy minden sztorit megvalósítottak volna.
A csapatban minden szerepkör képviselője megtalálható, így van benne fejlesztő és tesztelő
is. Téves azt gondolni, hogy a sprint elején a tesztelő is programot ír, hiszen, amíg nincs
program, nincs mit tesztelni. Ezzel szemben a tesztelő a sprint elején a tesztelő a teszttervet
készít, majd kidolgozza a teszteseteket, végül, amikor már vannak kész osztályok, unit-
teszteket ír, a változásokat regressziós teszttel ellenőrzi.
A Scrum, mint minden agilis módszertan, arra épít, hogy a fejlesztés közben a megrendelő
igényei változhatnak. A változásokhoz úgy alkalmazkodik, a Product Backlog folyamatosan
változhat. Az erre épülő dokumentumok folyamatosan finomodnak, tehát könnyen
változtathatók. A csapatok gyorsan megvalósítják a szükséges változásokat.
A Scrum tökélyre viszi az egy csapaton belüli hatékonyságot. Ha több csapat is dolgozik egy
fejlesztésen, akkor köztük lehetnek kommunikációs zavarok, ami a módszertan egyik
hátránya.
2-15
A Scrum két nagyon fontos fogalma a sprint és az akadály.
Sprint (vagy futam): Egy előre megbeszélt hosszúságú fejlesztési időszak, általában 2-4 hétig
tart, kezdődik a Sprint Planning-gel, majd a Retrospective-vel zárul. Ez a Scrum úgynevezett
iterációs ciklusa, addig kell ismételni, amíg a Product Backlog-ról el nem tűnnek a
megoldásra váró felhasználói sztorik. Alapelv, hogy minden sprint végére egy potenciálisan
leszállítható szoftvert kell előállítani a csapatnak, azaz egy prototípust. A sprint tekinthető
két mérföldkő közti munkának.
Akadály (Impediment): Olyan gátló tényező, amely a munkát hátráltatja. Csak és kizárólag
munkahelyi probléma tekinthető akadálynak. A csapattagok magánéleti problémái nem
azok. Akadály például, hogy lejárt az egyik szoftver licence, vagy szükség lenne egy plusz
gépre a gyorsabb haladáshoz, vagy több memóriára az egyik gépbe, vagy akár az is lehet,
hogy 2 tag megsértődött egymásra. Ilyenkor kell a Scrum Masternek elhárítani az
akadályokat, hogy a munka minél gördülékenyebb legyen.
Szerepkörök
A módszertan kétféle szerepkört különböztet meg, ezek a disznók és a csirkék. A
megkülönböztetés alapja egy vicc:
A disznó és a csirke mennek az utcán. Egyszer csak a csirke megszólal: „Te, nyissunk egy
éttermet!” Mire a disznó: „Jó ötlet, mi legyen a neve?” A csirke gondolkozik, majd rávágja:
„Nevezzük Sonkástojásnak!” A disznó erre: „Nem tetszik valahogy, mert én biztosan mindent
beleadnék, te meg éppen csak hogy részt vennél benne.”
A disznók azok, akik elkötelezettek a szoftver projekt sikerében. Ők azok, akik a „vérüket”
adják a projekt sikeréért, azaz felelősséget vállalnak érte. A csirkék is érdekeltek a projekt
sikerében, ők a haszonélvezői a sikernek, de ha esetleg mégse sikeres a projekt, akkor az
nem az ő felelősségük.
2-16
Disznók:
• Csapat (Team)
Csirkék:
• Menedzsment (Managers)
Termék tulajdonos (Product Owner): A megrendelő szerepét tölti be, ő a felelős azért, hogy a
csapat mindig azt a részét fejlessze a terméknek, amely éppen a legfontosabb, vagyis a
felhasználói sztorik fontossági sorrendbe állítása a feladata a Product Backlog-ban. A Product
Owner és a Scrum Master nem lehet ugyanaz a személy.
Megbeszélések
Sprint Planning Meeting (futamtervező megbeszélés): Ezen a találkozón kell megbeszélni,
hogy ki mennyi munkát tud elvállalni, majd ennek tudatában dönti el a csapat, hogy mely
sztorikat vállalja be a következő sprintre. Emellett a másik lényeges dolog, hogy a csapat a
Product Owner-rel megbeszéli, majd teljes mértékben megérti, hogy a vevő mit szeretne az
adott sztoritól, így elkerülhetőek az esetleges félreértésekből adódó problémák. Ha volt
2-17
Backlog Grooming, akkor nem tart olyan sokáig a Planning, ugyanis a csapat ismeri a Backlog-
ot, azon nem szükséges finomítani, hacsak a megrendelőtől nem érkezik ilyen igény. A
harmadik dolog, amit meg kell vizsgálni, hogy a csapat hogyan teljesített az előző sprintben,
vagyis túlvállalta-e magát vagy sem. Ha túl sok sztorit vállaltak el, akkor le kell vonni a
következtetést, és a következő sprintre kevesebbet vállalni. Ez a probléma leginkább az új,
kevéssé összeszokott csapatokra jellemző, ahol még nem tudni, hogy mennyi munkát bír
elvégezni a csapat. Ellenkező esetben, ha alulvállalta magát egy csapat, akkor
értelemszerűen többet vállaljon, illetve, ha ideális volt az előző sprint, akkor hasonló
mennyiség a javasolt.
Daily Meeting/Daily Scrum: A sprint ideje alatt minden nap kell tartani egy rövid
megbeszélést, ami maximum 15 perc, és egy előre megbeszélt időpontban, a csapattagok és
a Scrum Master jelenlétében történik (mások is ott lehetnek, de nem szólhatnak bele).
Érdekesség, hogy nem szabad leülni, mindenki áll, ezzel is jelezve, hogy ez egy rövid
találkozó. Három kérdésre kell válaszolnia a csapat tagjainak, ezek a következőek:
Sprint Review Meeting (Futam áttekintés): Minden sprint végén összeülnek a szereplők, és
megnézik, hogy melyek azok a sztorik, amelyeket sikerült elkészíteni, illetve az megfelel-e a
követelményeknek. Ekkor a sztori állapotát készre állítják. Fontos, hogy egy sztori csak akkor
kerülhet ebbe az állapotba, ha minden taszkja elkészült, és a Review-on elfogadták. Ezen a
megrendelő is jelen van.
Termékek
Product Backlog (termék teendő lista): Ez az a dokumentum, ahol a Product Owner elhelyezi
azokat az elemeket, más néven sztorikat, amelyeket el kell készíteni. Ez egyfajta
kívánságlista. A Product Owner minden sztorihoz prioritást, fontossági sorrendet rendel, így
2-18
tudja szabályozni, hogy melyeket kell elsősorban elkészíteni, így a Sprint Planning során a
csapattagok láthatják, hogy ami a Backlog-ban legfelül van, azt szeretné a vevő leghamarabb
készen látni, annak van a legnagyobb üzleti értéke. Emellett a csapatok súlyozzák az
elemeket aszerint, hogy melynek az elkészítéséhez kell a kevesebb munka, így azonos
prioritás mellett a kevesebb munkát igénylő elemnek nagyobb a befektetés megtérülése
(Return of Investment, ROI). Az üzleti érték meghatározása a Product Owner, a munka
megbecslése a csapat feladata. A kettő hányadosa a ROI.
Sprint Backlog (futam teendő lista): Ebben a dokumentumban az aktuális sprintre bevállalt
munkák, storyk vannak felsorolva, ezeket kell adott időn belül a csapatnak megvalósítania. A
sztorik tovább vannak bontva taszkokra, és ezeket a taszkokat vállalják el a tagok a Daily
Meeting során. Ez a feldarabolása a feladatoknak a feladat minél jobb megértését segíti.
Burn down chart (Napi Eredmény Kimutatás): Ez egy diagram, amely segít megmutatni, hogy
az ideális munkatempóhoz képest hogyan halad a csapat az aktuális sprinten belül. Könnyen
leolvasható róla, hogy a csapat éppen elakadt-e egy ponton, akár arra is lehet következtetni,
hogy ilyen iramban kész lesz-e minden a sprint végére. Vagy éppen ellenkezőleg, sikerült
felgyorsítani az iramot, és időben, vagy akár kicsit hamarabb is kész lehet a bevállalt munka.
• Tesztelés: Addig nem lehetünk benne biztosak, hogy egy funkció működik, amíg nem
teszteltük. Az extrém felfogás szerint kevés tesztelés kevés hibát talál, extrém sok
tesztelés megtalálja mind. A tesztelés játssza a dokumentáció szerepét. Nem
dokumentáljuk a metódusokat, hanem unit-teszteket fejlesztünk hozzá. Nem
készítünk követelmény specifikációt, hanem átvételi teszteseteket fejlesztünk a
megértett követelményekből.
2-19
• Tervezés: Tervezés nélkül nem lehet szoftvert fejleszteni, mert az ad- hoc megoldások
átláthatatlan struktúrához vezetnek. Mivel fel kell készülni az igények változására,
ezért úgy kell megtervezni a szoftvert, hogy egyes komponensei amennyire csak lehet
függetlenek legyenek a többitől. Ezért érdemes pl. objektum orientált tervezési
alapelveket használni.
• Teszt vezérelt fejlesztés (test driven development): Már a metódus elkészítése előtt
megírjuk a hozzá tartozó unit-teszteket. Ezt néha hívják először a teszt (test-first)
megközelítésnek is.
• Kódszépítés (refactoring): A már letesztelt, működő kódot lehet szépíteni, ami esetleg
lassú, rugalmatlan, vagy egyszerűen csak csúnya. A kódszépítés előfeltétele, hogy
legyen sok unit-teszt. A szépítés során nem szabad megváltoztatni a kód
funkcionalitását, de a szerkezet, pl. egy metódus törzse, szabadon változtatható. A
szépítés után minden unit-tesztet le kell futtatni, nem csak a megváltozott kódhoz
tartozókat, hogy lássuk, a változások okoztak-e hibát.
2-20
Az extrém programozás akkor működik jól, ha a megrendelő biztosítani tud egy munkatársat,
aki átlátja a megrendelő folyamatait, tudja, mire van szükség. Ha a változó, vagy a menet
közben kiderített követelmények miatt gyakran át kell írni már elkészült részeket, akkor az
extrém programozás nagyon rossz választás. Kezdő programozók esetén az extrém
programozás nem alkalmazható, mert nincs elég tapasztalatuk az extrém módszerek
alkalmazásához.
2-21
Tartalomjegyzék
2 A tesztelés helye a szoftver életciklusában ........................................................ ............. 2-1
2.1 A szoftverkrízis .............................. ................................................... ......................... 2-1
2.2 A szoftver életciklusa ........................ ................................................... ..................... 2-1
2.3 Módszertanok .................................. ................................................... ...................... 2-3
2.4 V-modell....................................... ................................................... .......................... 2-3
2.4.1 Prototípus modell ........................... ................................................... ................ 2-5
2.4.2 Iteratív és inkrementális módszertanok.......................................................... .. 2-7
2.4.3 Gyors alkalmazásfejlesztés – RAD ............................................................... .... 2-10
2.4.4 Agilis szoftverfejlesztés ...................................................................... ............. 2-12
2.4.5 Scrum ....................................... ................................................... ..................... 2-14
2.4.6 Extrém programozás .......................... ................................................... .......... 2-19
2-22
3 Statikus tesztelési technikák
A statikus tesztelési technikák a szoftver forrás kódját vizsgálják fordítási időben. Ide tartozik a
dokumentáció felülvizsgálata is. A statikus tesztelés párja a dinamikus tesztelés, amely a szoftvert
futásidőben teszteli.
• felülvizsgálat és
• statikus elemzés.
A felülvizsgálat a kód, illetve a dokumentáció, vagy ezek együttes manuális átnézését jelenti. Ide
tartozik például a páros programozás. A statikus elemzés a kód, illetve a dokumentáció
automatikus vizsgálatát jelenti, ahol a statikus elemzést végző segédeszköz megvizsgálja a kódot
(illetve a dokumentációt), hogy bizonyos szabályoknak megfelel-e. Ide tartozik például a helyesírás
ellenőrzés.
A statikus technikával más típusú hibák találhatóak meg könnyen, mint a dinamikus tesztelési
technikákkal. Statikus technikákkal könnyen megtalálhatóak azok a kód sorok, ahol null
referencián keresztül akarunk metódust hívni. Ugyanezt elérni dinamikus teszteléssel nagyon
költséges, hiszen 100%-os kód lefedettség kell hozzá. Ugyanakkor dinamikus teszteléssel könnyen
észrevehető, hogy ha rossz képlet alapján számítjuk pl. az árengedményt. Ugyanezt statikusan
nehéz észrevenni, hacsak nincs egy szemfüles vezető programozónk, aki átlátja az üzleti oldalt is.
A statikus tesztelési technikák előnye, hogy nagyon korán alkalmazhatóak, már akkor is, amikor
még nincs is futtatható verzió. Így hamarabb lehet velük hibákat találni és így gazdaságosabb a
hibajavítás.
3.1 Felülvizsgálat
A felülvizsgálat azt jelenti, hogy manuálisan átnézzük a forráskódot és fejben futtatjuk vagy
egyszerűen csak gyanús részeket keresünk benne. Ezzel szemben áll a statikus elemzés, ahol
szoftverekkel nézetjük át automatikusan a forráskódot. A felülvizsgálat fehérdobozos teszt, mivel
kell hozzá a forráskód. A felülvizsgálat lehet informális, pl. páros programozás, de akár nagyon
formális is, amikor a folyamatot jól dokumentáljuk, illetve a két szélsőség közti átmenetek.
Ehhez hasonló a páros programozás (pair programming) is. Ekkor két programozó ír egy kódot,
pontosabban az egyik írja, a másik figyeli. Ha a figyelő hibát lát vagy nem érti a kódot, akkor
azonnal szól. A két programozó folyamatosan megbeszéli, hogy hogyan érdemes megoldani az
adott problémát.
A kódszépítés (refactoring) egy másik módja a felülvizsgálatnak. Ilyenkor a már letesztelt, működő
kódot lehet szépíteni, ami esetleg lassú, rugalmatlan, vagy egyszerűen csak csúnya. A kódszépítés
előfeltétele, hogy legyen sok unit-teszt. A szépítés során nem szabad megváltoztatni a kód
funkcionalitását, de a szerkezet, pl. egy metódus törzse, szabadon változtatható. A szépítés után
minden unit-tesztet le kell futtatni, nem csak a megváltozott kódhoz tartozókat, hogy lássuk, a
változások okoztak-e hibát. A kódszépítést a szerző és egy tapasztalt programozó végzi közösen.
• hatékonysága függ az átnéző személyétől, minél tapasztaltabb, annál több hibát vehet
észre,
3.1.2 Átvizsgálás
Ez már kicsit formálisabb módja a felülvizsgálatnak. Általában a módszertan előírja, hogy az
elkészült kisebb-nagyobb modulokat ismertetni kell a csapat többi tagjával, a többi csapattal. Célja,
hogy a mások is átlássák az általunk írt kódrészletet (ez csökkenti a kárt, amit egy programozó
elvesztése okozhat, lásd kockázat menedzsment), kritikai megjegyzéseikkel segítsék a kód
minőségének javítását. Aszerint, hogy hány embernek mutatjuk be az elkészült modult, ezekről
beszélhetünk:
3-2
• váll feletti átnézés (over-the-shoulder review),
• körbeküldés (pass-around),
Váll feletti átnézés (over-the-shoulder review): Az egyik programozó egy ideje nézi saját
forráskódját, de nem találja a hibát. Valamelyik kollégáját megkéri, hogy segítsen. Mialatt
elmagyarázza a problémát, általában rá is jön a megoldásra. Ha mégsem, akkor a kollégának lehet
egy jó ötlete, hogy mi okozhatja a hibát. Általában ennyi elég is a hiba megtalálásához. Ha nem,
jöhet a forráskód átnézés.
Forráskód átnézés (code review): A kód írója megkér egy tapasztalt programozót, hogy segítsen
megtalálni egy nehezen megtalálható hibát. Együtt nyomkövetik a programot, miközben a szerző
magyarázza, mit miért csinált. Ellenőrzik, hogy a kód megfelel-e a specifikációnak. Ezt addig
fojtatják, amíg meg nem találják a hibát.
Kód átvétel (code acceptance review): Az elkészült nagyobb modulokat, pl. osztályokat, a vezető
fejlesztő vagy egy tapasztalt programozó átnézi, hogy van-e benne hiba, nem érthető, nem
dokumentált rész. A modul fejlesztői elmagyarázzák mit és miért csináltak. A vezető fejlesztő
elmondja, hogyan lehet ezt jobban, szebben csinálni. Ha hibát talál (ez gyakran logikai hiba), akkor
arra rámutat, vázolja a javítást.
Körbeküldés (pass-around): A kód szerzője körbeküldi az általa írt kódrészletet, ami akár egy egész
modul is lehet. A címzettek véleményezik a kódot, például megírják, melyik részét érdemes
tesztelni. A körbeküldés általában megelőzi a kód felvételét a verziókövető rendszerbe. Általában
csak akkor használják, ha egy kódrészlet kritikus fontosságú, pl. egy sokak által használt interfész.
Az intenzív kommunikációt előíró módszertanokra (pl. Scrum) nem jellemző.
Csoportos átnézés (team review): A csoportos átnézés a körbeküldést helyettesíti. Itt is egy
érzékeny kódrészletet néznek át többen, de interaktívan. A kódot a szerző prezentálja, sorról sorra
magyarázza. Általában elvárás, hogy ha valaki valamit nem ért, azonnal szóljon. A prezentáció
végén a vezető programozó elmondja, szerinte mit lehetett volna jobban csinálni. Ehhez is gyakran
hozzászólnak a többiek. Több módszertan (pl. extrém programozás) limitálja ezen alkalmak
időhosszát fél vagy egy órában.
Felület átnézés (interface review): Hasonló a csoportos átnézéshez, de itt általában több
embernek mutatjuk be azt az interfészt, amelyen keresztül a csoportunk fejlesztése lesz elérhető.
Ez azért fontos, hogy az egyes csoportok egyeztetni tudják elvárásaikat egymás felé. Ezeket rögzítik
3-3
és az integrációs teszt során felhasználják.
Kód prezentálás (code presentation): Hasonló a csoportos átnézéshez, de az érdekes kódot nem a
csoporton belül, hanem a cégen belül mutatjuk be. Akkor gyakori, ha több telephelyen fejlesztik
ugyanazt a szoftvert. Nem feltétlenül az egész cég vesz részt benne, lehet, hogy csak három ember,
de könnyen előfordulhat, hogy ezek más-más kontinensen vannak. A kód prezentálás célja lehet
egy hiba bemutatása, amit egy másik csapat talált és megkéri a kód tulajdonosát, hogy javítsa.
Másik gyakori cél a csúcs fejlesztők összehozása, hogy a keretrendszer továbbfejlesztését
megbeszéljék.
• a szerzők jól felkészülnek, pl. szemléltető ábrákat készítenek, a többi résztvevő átnézi a
kapcsolódó dokumentációt,
Ilyenkor külső szakértőket szoktak felkérni, hogy segítsenek. Leggyakrabban egy-egy lekérdezés
bizonyul túl lassúnak. Ilyenkor egy index hozzáadás a táblához nagyságrendekkel gyorsítja a
lekérdezést. A kérdés már csak az, mit indexeljünk és hogyan. A külsős szakértők átnézik a
megoldásunkat és javaslatokat adnak.
Mivel ez a fajta tanácsadás nagyon drága, ezért ez egy jól dokumentált folyamat. A szoftvercég
leírja, hogy mi a probléma. Mind a cég alkalmazottai, mind a szakértők felkészülnek, átnézik a
dokumentációkat. A megbeszélést általában egy moderátor vezeti, aki jegyzőkönyvet is ír. A
moderátor nem lehet a program írója. A résztvevők megbeszélik, hogy mi a probléma gyökere. A
szakértők több megoldási javaslatot is adnak. Kiválasztanak egy megoldást. Ezt vagy a szerző, vagy
a szakértők implementálják.
A technikai vizsgálat másik típusa, amikor külső szakértők azt ellenőrzik, hogy a szoftver vagy a
dokumentációja megfelel-e az előírt szabványoknak. Az ellenőrzést nem a megrendelő, hanem a
3-4
szoftver cég vagy a szabvány hitelesítését végző szervezet kezdeményezi. Pl. az emberi életre is
veszélyes (life-critical) rendszerek dokumentációjára az IEC61508 szabvány vonatkozik. Ennek
betartása a cég érdeke, mert ha kiderül, hogy nem tartja be a szabványt, akkor a termékeit akár ki
is vonhatják a piacról.
Akkor is ehhez a technikához fordulnak, ha a szoftverben van egy hiba, amit nagyon nehéz
reprodukálni, és a szoftver cég saját alkalmazottai nem tudják megtalálni (megtalálhatatlan hiba).
Ez többszálú vagy elosztott rendszereknél fordul általában elő egy holtpont (deadlock) vagy
kiéheztetés (starvation) formájában, de lehet ez egy memóriaszivárgás (memory lake) is. Ilyenkor a
szakértő megmutatja, hogyan kell azt a statikus elemző szoftvert használni, pl. egy holtpont
keresőt (deadlock checker), ami megtalálja a hibás részt. Az így feltárt hibát általában már a cég
szakemberei is javítani tudják.
3.1.4 Inspekció
Ez a legformálisabb felülvizsgálat. Ezt is akkor használjuk, ha külső szakértő bevonására van
szükségünk. A technikai felülvizsgálattól az különbözteti meg, hogy a szoftver cég és a szakértőt
adó cég részletesebb szerződést köt, amely magában foglalja:
Míg a technikai átnézésnél gyakran csak annyit kérünk a szakértőktől, hogy legyen sokkal gyorsabb
egy lekérdezés, az inspekció esetén leírjuk pontosan, hogy milyen gyors legyen.
Az inspekció szó abból jön, hogy a probléma megoldásához általában nem elég csak a szoftver egy
részét átvizsgálni, hanem az egész forráskódot adatbázissal együtt inspekció alá kell vonni.
Inspekciót alkalmazunk akkor is, ha egy régi (esetleg már nem támogatott programozási nyelven
íródott) kódot akarunk szépíteni / átírni, hogy ismét rugalmasan lehessen bővíteni.
3-5
Az inspektornak nagy tekintélyű szakembernek kell lennie, mert az általa javasolt változtatások
általában nagyon fájóak, nehezen kivitelezhetőek. Ha nincs meg a bizalom, hogy ezekkel a
változtatásokkal el lehet érni a célt, akkor a fejlesztő csapat ellenállásán elbukhat a
kezdeményezés.
Az inspekció lehet rövid távú is (egy-két hetes), ha a szakértőre nincs szükség a probléma
megoldásához, csak a feltárásához. Ekkor a szakértő egy inspekciós jelentést ír, amely leírja,
hogyan kell megoldani a problémát. Ehhez általában csatolni kell egy példa programot is, egy
úgynevezett PoC-kot (Proof of Concept), amely alapján a cég saját fejlesztői is képesek megoldani
a problémát. A PoC-oknak demonstrálnia kell, hogy a kívánt metrika értékek elérhetőek a
segítségével.
• célja teljesítmény fokozás a szakértő által kiválóan ismert technológia segítségével vagy
elavult kód frissítése.
A statikus elemzés azt használja ki, hogy az ilyen tipikus hibák leírhatók egyszerű szabályokkal,
amiket egy egyszerű kódelemző (parser) gyorsan tud elemezni. Például null referencia hivatkozás
akkor lehetséges, ha egy „a = null;” értékadó utasítás és egy „a.akármi;” hivatkozás közt van olyan
végrehajtási út, ahol az „a” referencia nem kap null-tól különböző értéket. Ugyan ezt lehet
dinamikus technikákkal is vizsgálni, de ahhoz annyi tesztesetet kell fejleszteni, ami minden
lehetséges végrehajtási utat tesztel az „a = null;” és az „a.akármi;” közt.
3-6
A forráskód statikus elemzésnek két változata ismert, ezek:
Ezen túl lehetséges a dokumentumok statikus elemzése is, de ezekre nem térünk ki.
A következő hiba típusokat könnyebb statikus elemzéssel megtalálni, mint más technikákkal:
• holtpontok (deadlock),
• kiéheztetés (starvation).
Az egyes eszközök lehetnek specifikusak, mint pl. a holtpont keresők, illetve általánosak, mint pl. a
FindBugs.
Jelen jegyzetben a FindBugs használatát fogjuk bemutatni Eclipse környezetben. Először telepíteni
kell a FindBugs plugint. Ehhez indítsuk el az Eclipse rendszert, majd válasszuk a Help -> Install New
Software… menüt. A megjelenő ablakban adjuk hozzá a plugin források listájához az alábbi linket
az Add gombbal: http://findbugs.cs.umd.edu/eclipse. Ezután néhány Next gomb és a felhasználási
feltételek elfogadása után a rendszer elkezdi installálni a FindBugs plugint. Ez néhány percet vesz
igénybe, ami után újraindul az Eclipse. Ezután már használhatjuk a FindBugs-t.
A használatához válasszunk ki egy projektet, majd a helyi menüben válasszuk a Find Bugs -> Find
Bugs menüt. Ez egyrészt megkeresi azokat a sorokat, amelyek valamilyen szabálynak nem felelnek
meg, másrészt átvisz minket a FindBugs perspektívába. Ha talál hibákat, akkor ezeket bal oldalon
egy kicsi piros bogár ikonnal jelzi. Ha ezekre ráállunk vagy rákattintunk, akkor láthatjuk, milyen
típusú hibát találtunk. Ezekről részletes információt is kérhetünk, ha a FindBugs perspektíva Bug
Explorer ablakában kiválasztjuk valamelyiket.
Az egyes hibák ellenőrzését ki/be lehet kapcsolni a projekt Properties ablakának FindBugs panelén.
3-7
Itt érdemes a Run atomatically opciót bekapcsolni. Így minden egyes mentésnél lefut a FindBugs.
Ebben az ablakban az is látható, melyik hiba ellenőrzése gyors, illetve melyik lassú. Például a null
referenciára hivatkozás ellenőrzése lassú.
Itt több hibát is kapunk: „Overwritten increment” és „Self assignment of local variable”. Az első
hiba arra utal, hogy hiába akartuk növelni az i változó értékét, az elvész. A második hiba azt fejezi
ki, hogy egy változót önmagával akarunk felülírni.
A fenti esetre a „Possible null pointer dereference of o” hibát kapjuk, habár egyértelműen látszik,
hogy az o értéket fog kapni, hiszen igaz az if utasítás feltétele. Ugyanakkor a FindBugs rendszer
nem képes kiszámolni a változók lehetséges értékeit az egyes ágakon, hiszen nem tartalmaz egy
automatikus tételbizonyítót. Ezzel szemben a következő alfejezetben tárgyalt ESC/Java2 eszköz
képes erre, hiszen egy automatikus tételbizonyítóra épül.
3-8
Egy példa assert használatára:
public double division(double a, double b){
assert(b!=0.0);
return a / b;
}
A fenti példában azt feltételezzük, hogy a metódus második paramétere nem nulla. A program
kódjában a feltételezéseinket assert formájában tudjuk beírni Java esetén. Java esetén az assert
utasítások csak akkor futnak le, ha a JVM-et a –enableassert vagy az egyenértékű –ea opcióval
futtatjuk, egyébként nincs hatásuk.
A program viselkedését legegyszerűbben assert utasítások lehet leírni, de lehetőségünk van magas
szintű viselkedés leíró nyelvek használatára, mint például a JML (Java Modeling Language) nyelv.
Ez esetben magas szintű statikus kód ellenőrzést (Extended Static Checking, ESC) tudunk végezni az
ESC/Java2 program segítségével.
Az fenti példában van egy BankSzámla osztályunk, amelyben a balansz mező tárolja, hogy mennyi
pénzünk van. Az invariánsunk az fejezi ki, hogy a balansz nem lehet negatív. Négy metódusunk van.
A metódusoknál megadjuk elő- és utófeltételüket természetes nyelven:
betesz(összeg)
Előfeltétel: Az összeg pozitív szám, mert nulla forintot nincs értelme betenni, negatív
összeget pedig nem szabad.
Utófeltétel: A balanszot meg kell növelni az összeggel, azaz az új balansz a régi balansz
plusz az összeg.
kivesz(összeg)
Előfeltétel: Az összeg pozitív szám, mert nulla forintot nincs értelme kivenni, negatív
összeget pedig nem szabad. Továbbá az összeg kisebb egyenlő, mint a balansz, mert a
számlán lévő összegnél nem lehet többet felvenni.
zárol()
3-10
Előfeltétel: Nincs, azaz mindig igaz.
getBalansz()
Kivétel: Zárolt számla nem kérdezhető le, ezért BankingException kivételt kell dobni.
Keret feltétel: Mindkét esetben egyik mező sem írható, tehát ez a metódus „pure”.
A JML nyelvhez több segédeszköz is létezik. Az első ilyen az Iowa State University JML program. Ez
a következő részekből áll:
jmlc: Java és JML fordító, a Java forrásban lévő JML specifikációt belefordítja a bájtkódba.
jmlrac: a jmlc által instrumentált bájtkódot futtató JVM, futtatás közben ellenőrzi a
specifikációt, tehát dinamikus ellenőrzést végez.
Nekünk a JML 5.4 és 5.5 verziót volt szerencsénk kipróbálni. Sajnos ezek csak a Java 1.4 verzióig
támogatják a Java nyelvet. Nem ismerik például a paraméteres osztályokat. Ha simán hívjuk meg a
jmlc parancsot, akkor rengeteg információt kiír, ami esetleg elfed egy hibát. Ezért érdemes a -Q
vagy a -Quite opcióval együtt használni. A BankSzámla példát a következő utasításokkal lehet
ellenőrizni, hogy megfelel-e specifikációjának:
jmlc -Q BankSzámla.java
jmlrac BankSzámla
Persze ehhez a BankSzámla osztályba kell írni egy main metódust is, hiszen az a belépési pont.
Második példa:
package bank3;
3-11
public abstract class AbstractAccount {
package bank3;
Ez a példa azt mutatja meg, hogyan lehet már az interfészben vagy az absztrakt ős osztályban
specifikálni az elvárt viselkedést. Ehhez egy modell mezőt kell definiálni az ősben (vagy az
interfészben) a „model” kulcsszóval. A konkrét gyermekben az ősben specifikált viselkedést meg
kell valósítani. Ehhez meg kell mondani, hogy melyik konkrét mező valósítja meg a modell mezőt.
Ez a „represents” kulcsszó használatával lehetséges.
3-12
A fenti példát a következő utasításokkal lehet ellenőrizni:
jmlc -Q bank3/*.java
jmlrac bank3.Account
Persze ehhez a Account osztályba kell írni egy main metódust is, hiszen az a belépési pont.
Harmadik példa:
package bank4;
package bank4;
Ez a példa azt mutatja meg, hogyan kell modell mezőt létrehozni az interfészben. Mindent
ugyanúgy kell csinálni, csak a „model” kulcsszó elé be kell írni az „instance” kulcsszót, ami azt fejezi
ki, hogy a modell változó példány szintű. Erre azért van szükség, mert egyébként Javában minden
interfész mező statikus.
Láttuk, hogy a specifikáció dinamikus ellenőrizhető az Iowa State University JML programmal.
Szerencsére lehetséges a statikus ellenőrzés is az ESC/Java2 programmal.
Az ESC/Java2 (Extended Static Checker for Java2) egy olyan segédeszköz, amely ellenőrizni tudja,
hogy a Java forrás megfelel-e a JML specifikációnak. Az ESC/Java2 hasonlóan a FindBugs
3-13
programhoz figyelmezteti a programozót, ha null referenciára hivatkozik, vagy más gyakori
programozói hibát vét. Erre akkor is képes, ha egy JML sor specifikációt se írunk. Nyilván, ha
kiegészítjük a kódunkat JML specifikációval, akkor sokkal hasznosabban tudjuk használni.
Az ESC/Java2 program is csak a Java 1.4 verziójáig támogatja a Java nyelvet. Ez is telepíthető
Eclipse pluginként a http://kind.ucd.ie/products/opensource/Mobius/updates/ címről.
A második perspektívában 5 új gombot kapunk. Ezek közül a legfontosabb az első, amely elindjtja a
ESC/Java2 ellenőrző programot. A többi gomb balról jobbra haladva a következők: jelölők
(jelölőknek nevezzük a hiba helyét jelölő piros ikszet) törlése, ugrás jelölőre, ellenörzés
engedélyezése, ellenőrzés tiltása. Ezeket nem találtuk különösebben hasznosnak. Ami hasznos volt
számunkra az az ESC/Java2 menüben található Setup menü. Itt lehet bekapcsolni az automatikus
ellenőrzést, aminek hatására minden egyes mentés után lefut az ESC/Java2.
Nézzünk egy egyszerű példát, amikor JML specifikáció nélkül is hibát fedez fel a kódunkban az
ESC/Java2.
package probe;
Car target;
return target.getSpeed();
Itt az ötödik sorra azt a hibát kapjuk, hogy „Possible null dereference (Null)”. Ez a figyelmeztetés
teljesen jogos, segíti a programozót kijavítani egy hibát.
Erre az ESC/Java2 semmilyen hibát nem ad. Ez azért lehetséges, mert mögötte egy automatikus
tételbizonyító áll, ami meg tudja nézni, hogy valamely feltétel igaz vagy sem az egyes lehetséges
végrehajtási utakon.
3-14
Ugyanakkor a ESC/Java2-höz adott Simplify nevű automatikus tételbizonyító nem túl okos. Például
nem tudja, hogy két pozitív szám szorzata pozitív, ezért ad hibát a következő példára:
if (n==0) return 1;
return n*fact(n-1);
Itt az ESC\Java2 hibásan a „Postcondition possibly not established (Post)” figyelmeztetést adja,
pedig a függvény tökéletesen betartja az utófeltételét. Szerencsére az ESC\Java2 alatt kicserélhető
az automatikus tételbizonyító.
3-15
Tartalomjegyzék
3 Statikus tesztelési technikák ...................................................................... ............................................. 3-1
3.1 Felülvizsgálat................................. ................................................... ............................................... 3-1
3.1.1 Informális felülvizsgálat ........................ ................................................... ............................... 3-2
3.1.2 Átvizsgálás ...................................... ................................................... ..................................... 3-2
3.1.3 Technikai felülvizsgálat ......................... ................................................... ............................... 3-4
3.1.4 Inspekció ........................................ ................................................... ...................................... 3-5
3.2 Statikus elemzés .............................. ................................................... ............................................ 3-6
3.2.1 Statikus elemzés csak a forráskód alapján ........................................................... .................. 3-7
3.2.2 Statikus elemzés a forráskód és modell alapján ...................................................... ............... 3-8
3-16
Szoftver tesztelés
A dinamikus tesztelési technikák elsősorban a komponens teszt, azon belül is főleg a unit-
teszt (egységteszt) fázis eszköze.
Mivel a teszteléssel kapcsolatos magyar nyelvű irodalom máig is igen kevés, az érdeklődőbb
hallgatók elsősorban az angol nyelvű szakirodalom tanulmányozása során juthatnak új
ismeretekhez. Ennek megkönnyítésére a fontosabb fogalmak első előfordulása során annak
angol nyelvű megnevezését is közöljük.
4.1 Alapfogalmak
A dinamikus tesztek tervezése alapvetően az alábbi három lépésből áll:
• funkció,
• tranzakció,
• képesség (feature),
• minőségi jellemző,
• strukturális elem.
4-1
Szoftver tesztelés
4.1.2 Teszteset
Egy teszteset az alábbi összetevőkből áll:
Egy teszteset végrehajtása esetén a rendszert egy megadott kezdő állapotban kell hozni
(prekondíciók), megadott input értékek halmazával végre kell hajtatni a tesztelt elemet,
majd a teszt futásának eredményét össze kell hasonlítani az elvárt eredménnyel és
ellenőrizni kell, hogy a végrehajtás után a rendszer az elvárt állapotba (posztkondíciók)
került-e.
Példaként tételezzünk fel egy olyan program modult, amely a felhasználótól bekér néhány
adatot, és megnyomja a „Számolj”gombot. A modul a megadott adatokat és adatbázisban
tárolt egyéb értékeket felhasználva elvégez valamilyen számítást, majd az eredményeket
adatbázisba menti. Ennek a modulnak egy tesztesete tartalmazza:
4.1.4 Tesztkészlet
Egy tesztkészlet tesztesetek és hozzájuk tartozó teszt specifikációk halmaza. Csoportosítható
egy teszt alanyra, vagy egy vizsgált hibára.
A tesztkészletet megfelelő módon archiválni kell, mert egy tesztkészletet a fejlesztés során
többször is végre kell hajtani, sőt, a rendszer későbbi változtatásainál is szerepet kap, annak
ellenőrzésére használható, hogy a változtatás hatására nem keletkezett-e újabb hiba.
4-2
Szoftver tesztelés
4.1.5 Hibamodell
Azon (feltételezett) szoftver hibák halmaza, amelyre a teszt tervezés irányul. A tesztesethez
kapcsolódó példához a hibamodell azt rögzítheti, hogy az alábbi hibák következhetnek be:
• számítási hibák,
• adatbázis lekérdezési hibák (rossz adatokat használunk fel a számításhoz),
• az adatbázisba módosításának hibák (a számítás eredménye rosszul kerül be az
adatbázisba).
Amióta felismertük, hogy a tesztelés a fejlesztési folyamat fontos (és sajnos erőforrás
igényes, tehát költséges) része, folyamatosan keressük a folyamat előrehaladásának a mérési
lehetőségeit.
4-3
Szoftver tesztelés
• Lehetőség biztosít arra, hogy megbecsüljük, ennyi erőforrást kell még a fejlesztési
projekt hátralevő idejében tesztelési tevékenységre fordítani.
A lefedettségi mérőszámok tehát arra nézve adnak információt, hogy milyen készültségi
szinten áll a tesztelési tevékenység, és a tesztelési terv részeként meghatározzák, hogy
milyen feltételek esetén tekinthetjük a tevékenységet késznek.
Természetesen léteznek olyan teszt tervezési módszerek is, amelyek egyik fenti kategóriába
sem sorolhatók be, azonban a gyakorlatban alkalmazott módszerek összefogására a jelen
jegyzet szintjén ezek a kategóriák beváltak.
4-4
Szoftver tesztelés
A specifikáció soha nem azt rögzíti, hogy hogyan kell a rendszernek megvalósítania az elvárt
viselkedést (ennek meghatározása a tervezés feladata), csak magát a viselkedést definiálja. A
specifikáció és a tervezés a fejlesztés folyamatában is külön fázist képviselnek, és gyakran a
fejlesztő csoporton belül nem is ugyanazok a részvevők végzik. A specifikációs fázis
legtöbbször megelőzi a tervezési fázist. Ez lehetővé teszi a munkafolyamatok
párhuzamosítását: a specifikáció alapján a tesztmérnökök kidolgozhatják a teszteseteket
miközben a rendszer tervezése és implementálása folyik. Ha az implementáció elkészül, a
már kész tesztesetek futtatásával lehet ellenőrizni.
Nem minden fejlesztési projekt alapul pontosan definiált specifikáción. Ebben az esetben a
specifikáció alapú tesztesetek megtervezése, illetve a tervezéshez szükséges információk
megszerzése párhuzamosan, egymástól elkülönítve történhet, ami többlet erőforrások
felhasználását, és a félreértések esélyének növekedését jelenti.
Van azonban olyan eset is, amikor a formális specifikáció hiánya nem jelenti a tesztelési
tevékenység megnehezítését. Az agilis fejlesztési szemlélet ugyanis nem követeli meg
formális specifikáció elkészítését. Ez a megközelítés azonban éppen a tesz tervezés
fontosságát emeli ki: a specifikáció szerepét a tesztesetek veszik át: a fejlesztés során először
egy funkcióhoz tartozó teszteseteket kell megtervezni. Az implementációs fázis befejezését
az jelenti, ha az összes (előre megtervezett) teszteset hiba kimutatása nélkül fut le.
S1: Készítsünk programot, amely beolvas egy egész számot, és kiírja, hogy az negatív, pozitív,
vagy nulla-e.
S2: Készítsünk programot, amely beolvas három egész számot, amelyek egy háromszög
oldalhosszait reprezentálják. A feladat annak megállapítása, hogy a bemeneti adatok
általános, egyenlőszárú vagy egyenlő oldalú háromszöget alkotnak-e.
4-5
Szoftver tesztelés
Ekvivalencia osztálynak nevezzük az input értékek olyan halmazát, amelyre ugyanúgy kell
viselkednie a programnak. Ez azt jelenti, hogy egy ekvivalencia osztályhoz elég egy teszt
esetet megtervezni és lefuttatni, mert az osztályhoz tartozó lehetséges tesztesetek
• három olyan pozitív szám, ami általános háromszöget alkot (érvényes ekvivalencia
osztály)
• Az egyik szám negatív (nem érvényes ekvivalencia osztály)
• stb.
4-6
Szoftver tesztelés
Figyelni kell a kimeneti ekvivalencia osztályok határértékeit is. Ehhez persze sokszor
"visszafelé" kell gondolkodni, tehát meg kell határozni azon input értékek halmazát, amelyek
határértékként kezelhető kimeneteket produkálnak.
Példaként vegyük egy program modult, amelynek feladata egy minta megkeresése egy
sorozatban. A határérték analízis során megtalálható tesztesetek:
• 0 hosszúságú sorozat
• 1 hosszúságú sorozat, a minta nincs benne / a minta benne van
• >1 hosszúságú sorozat, a minta az első / utolsó helyen van
• 2 hosszúságú sorozat (nincs benne / első /utolsó)
• nagyon nagy elemszámú sorozat
A módszer alapgondolata az, hogy a specifikáció gyakran olyan formában írja le a rendszer
által megvalósítandó üzleti folyamatokat, hogy az egyes tevékenységeknek milyen bemeneti
feltételei vannak. Az előző két módszer nem vizsgálja a bementi feltételek kombinációit.
4-7
Szoftver tesztelés
okokat és a hatásokat soroljuk fel, a cellákban pedig azok logikai értéke található. A táblázat
minden egyes oszlopa egy megvalósítandó teszt esetet definiál.
Egy áruház pontgyűjtő kártyát bocsát ki. Minden vásárló, akinek van ilyen kártyája, minden
vásárlása során dönthet, hogy 5% kedvezményt kér a számla összegéből, vagy a kártyán lévő
pontjait növeli meg. Az a vásárló, akinek nincs ilyen kártyája, szintén megkaphatja az 5%
kedvezményt, ha 50.000 Ft felett vásárol.
• Nincs kedvezmény
• Kedvezmény jóváírása
• Pontok jóváírása
A döntési tábla:
T1 T2 T3 T4
Okok:
O1 Van-e pontgyűjtő kártya? I I H H
O2 Kéri-e a kártyatulajdonos a H I - -
kedvezményt?
O3 50.000 Ft felett van-e a vásárlás - - H I
összege?
Hatások:
H1 Nincs kedvezmény I H I H
H2 Kedvezmény jóváírása H I H I
H3 Pontok jóváírása I H H H
A táblázatban az Igaz – Hamis logikai értékek mellett megjelenik a – jel is, amelynek kétféle
jelentése lehet:
Ez a jelölés (amely egyfajta háromértékű logikát használ) csökkenti az oszlopok (és ezzel a
szükséges tesztesetek) számát.
4-8
Szoftver tesztelés
A specifikációból előállított döntési tábla, amellett hogy jól áttekinthető kiindulópontja lehet
a tesztesetek tervezésének, „mellékhatásként” alkalmas a specifikáció konzisztenciájának és
teljességének az ellenőrzésére is, ezáltal a specifikáció tesztelésének is eszköze. A
specifikáció hiányosságaira utalhat például az, hogy táblázatban tudunk olyan oszlopot
előállítani, amelyben a bemeneti feltételeknek egy, a valóságban előfordulható kombinációja
található, de nem tartozik hozzá a specifikációban hatás. (Hiányos specifikáció.)
A döntési tábla előállításának van egy formális módszere, amely főleg nagy méretű
táblázatok esetén lehet hasznos. Ehhez ismét abból kell kiindulni, hogy a rendszert egy
logikai hálózatként tekinthetjük, ahol a bementi feltételek, a döntésekhez szükséges
közbenső feltételek és a kimenetet jelentő hatások a hálózat elemei. Az ilyen hálózatokat az
úgynevezett bool gráffal ábrázolhatjuk. A bool gráf jellemzői:
4-9
Szoftver tesztelés
4-10
Szoftver tesztelés
A véletlenszerű adatok generálása mindig egy adott tartományba eső (általában egyenletes
eloszlású) számok előállítását jelentik. A tartomány lehet az adott adat érvényességi
tartomány, vagy éppen azon kívüli (ebben az esetben a rendszernek a hibás bemenetekre
adott válaszát tesztelhetjük).
Terhelési tesztként használva gyakran lehet becslésünk arról, hogy a bemenetei adatok az
éles használat esetén milyen eloszlást követnek, ilyenkor az egyenletes eloszlás helyett a
becsült eloszlásnak megfelelő adatokat generálhatunk.
4-11
Szoftver tesztelés
Használati esetek
Test eset 1 2 3 4 5
1
2
3
4
5
A szürkített cellák azt mutatják, hogy melyik teszteset melyik használati eset funkcióinak
tesztelésére szolgál. A teszt lefedettségi mátrix segíthet a tesz futtatások ütemezésében, és
ellenőrizhető segítségével, hogy minden használati esethez tartozik-e legalább egy teszt
eset.
• A valós feladatnál sokkal kisebb méretű feladatot adunk teszt esetként, amit kézzel is
végig lehet számolni.
• Ugyanazt a problémát más programmal is megoldatjuk, és annak az eredményét
használjuk fel a teszt kimenetének ellenőrzésére.
• Szimulációs szoftvert használunk.
• Bár a kimenetet számszerűen nem tudjuk ellenőrizni, de tudjuk, hogy az
eredménynek bizonyos szerkezeti sajátosságokat kell mutatnia.
Példaként említhetünk egy olyan projektet, amelyben jelen fejezet szerzőjének egy geofizikai
modellező rendszer programjának elkészítése volt a feladata. A matematikai modell egyik
része egy több százezer ismeretlenes lineáris egyenletrendszer együttható mátrixának a
felépítését és az egyenletrendszer megoldását igényelte. Nyilvánvaló, hogy ennek a
modulnak a kimenetét nem lehet úgy ellenőrizni, hogy kézzel kiszámítjuk az eredményt. A
tesztelés ezért több lépcsőben történt:
• Először egy erősen redukált elemszámú (tíz körüli ismeretlent tartalmazó) feladatot
oldattunk meg, amelynek természetesen fizikai realitása nincs, de az eredményét
manuálisan is lehet ellenőrizni. A „manuális ellenőrzés” persze már ebben az esetben
is jelentheti segédprogramok igénybevételét.
• A következő lépcső az együtthatómátrix valós értékei helyett olyan speciális értékek
beállítását jelentette, amellyel az egyenletrendszer megoldásának helyességét
könnyű tesztelni. (Például ha az együttható mátrix az egységmátrix, akkor a megoldás
vektornak azonosnak kell lennie a jobboldal vektorával.)
4-12
Szoftver tesztelés
Ebben a szemléletben a tesztesetek megtervezése során az a cél, hogy a vizsgált kód minden
ágát végrehajtva vizsgáljuk annak működését. Mivel egy bonyolult kód végrehajtási útjainak
száma nagyon magas lehet, általában nem túl nagy egységek képezik a tesztelés tárgyát.
A vezérlési folyamat gráf egy olyan irányított gráf, amelyben a csomópontok a program
utasításainak felelnek meg, az irányított élek pedig a végrehajtásuk sorrendjét jelölik ki. Egy
döntési utasításnak megfelelő csomópontból több él indul ki, a vezérlési ágak
összekapcsolódási pontjában elhelyezkedő utasításhoz pedig több él fut be. A ciklust
visszafelé irányuló él reprezentálja.
4-13
Szoftver tesztelés
Szabványok előírásai
Mivel azonban a feltételek nem mindig függetlenek egymástól, a bejárható utak száma
általában kevesebb, mint az összes út.
Általános tesztelési cél, hogy a teszthalmaz fedje le a független utak egy maximális (további
független utakkal már nem bővíthető) halmazát. Ennek a célnak a megvalósítását az alábbi
problémák nehezíthetik:
• Az ilyen utak halmaza nem egyedi, tehát ugyanahhoz a kódhoz akár több ilyen
halmazt is lehet rendelni, ami több teszteset halmazt is jelenthet.
• Mivel a ciklomatikus komplexitás a független utak számának felső korlátja, egyes
halmazok számossága lehet kisebb, mint a ciklometrikus komplexitás.
Ebben a lépésben már adódnak problémák. Ha vezérlési gráf kört tartalmaz (márpedig
tartalmaz, mert elég nehéz értelmes kódot elképzelni ciklus nélkül), az elvben végtelen
4-14
Szoftver tesztelés
számú út generálását tenné lehetővé. Ne felejtsük el, hogy a vezérlési gráf nem tartalmaz
futás közbeni értékeket, így egy ciklus menetszáma (ami a valóságban természetesen véges)
a gráfból nem állapítható meg. Ez a probléma kezelhető, de a generálandó utak számának
növekedését jelenti. Különösen igaz ez az egymásba ágyazott ciklusok esetén. A struktúra
alapú tesztelési technikák legnagyobb kihívását éppen a ciklusok kezelése jelenti.
Ebben a lépésben az okozhat problémát, hogy egy adott úthoz nem feltétlenül generálható
olyan bemeneti kombináció, amely annak a bejárását eredményezné. Ez persze nem jelenti
feltétlenül azt, hogy az adott út elemeit képező utasítások elérhetetlenek, csak azt, hogy egy
másik út részeként hajtódhatnak végre.
Az idők során számos ilyen mérőszámot dolgoztak ki, és megoldott ezen mérőszámok
automatikus számítása is. A mérőszámok általában 0 és 1 közé eső értékek. Azt
mondhatnánk tehát, hogy a tesztelés akkor teljes, ha egy ilyen mérőszám értéke 1 (teljes
lefedettség), azonban:
• A teljes lefedettség sokszor csak irreálisan nagy teszteset halmazzal érhető el, ezért
inkább annak csak minél jobb megközelítésére törekedhetünk.
• A 100%-os lefedettség sem jelenti azt, hogy minden hibát megtaláltunk. (Erre
példákat az egyes mérőszámok ismertetésénél mutatunk.)
• Mivel a különböző lefedettségi mérőszámok más és más szempontból értékelik a
tesztelés alaposságát, célszerű többet is használni.
Itt hívnám fel arra a figyelmet, hogy a kód lefedettségi mutató nem azonos a hiba
lefedettséggel (amit nem is tudunk számítani, hiszen ahhoz ismerni kellene a programban
levő hibák számát). A kód lefedettség a tesztelés alaposságát méri, a hiba lefedettség az
eredményességét. A tapasztalatok alapján azonban abban bízhatunk, hogy az alapos
tesztelés az eredményességet is növeli.
• utasítás lefedettség,
4-15
Szoftver tesztelés
S(c) = s/S
A 100% még nem biztosíték arra, hogy a teljes tesztelés minden hibát megtalál.
int a=5 ;
x= …;
if (x>0) a = 10;
a = 20;
D(c) = d/D
A döntés lefedettség tehát akkor teljes, ha a programban szereplő összes döntés minden
lehetséges kimenete előfordult a tesztelés során.
u1;
else
u2;
4-16
Szoftver tesztelés
A teljes lefedettséghez két teszteset szükséges, hiszen egy feltételnek két lehetséges
kimente van. Ez a két teszteset lehet például:
Ebben a két tesztesetben egyszer sem volt szükség a harmadik operandus kiértékelésére,
tehát a függvény nem hívódik meg. Ha abban van hiba, az felderítetlen marad.
4.4.4.3 Út lefedettség
Számítási módja:
P(c) = p/P
ahol p a tesztelés során bejárt utak száma, P pedig a vezérlési gráf összes útjainak a száma
• Az összes utak száma nagyon nagy lehet, ezért a tesztesetek generálása és lefuttatása
erőforrás igényes.
• A vezérlési gráfban lehetnek nem bejárható utak az egymást kizáró feltételek miatt,
tehát a teljes lefedettség nem is mindig elérhető.
4-17
Szoftver tesztelés
A hiba becslés módszerét strukturáltabbá lehet tenni azzal, hogy elkészítünk egy potenciális
hibalistát. A lista a tesztelő és a felhasználó előzetes tapasztalatai alapján készülhet, és
segítheti a szisztematikus módszereket, de további teszteseteket is generálhat.
4.7 Irodalomjegyzék
Brian Hambling (Editor), Peter Morgan, Angelina Samaroo, Geoff Thompsom, Peter Wiliams:
Software Testing; an ISEB Foundation. The British Computer Society (BCS), 2007. ISBN
1.902505-79-4
4-18
Szoftver tesztelés
ftp://jegyzet.sth.sze.hu/!BSc/Szoftverminosegbiztositas/SW_minosegbizt.pdf
4-19
Szoftver tesztelés
Tartalomjegyzék
4-20
Szoftver tesztelés
4-21
Szoftver tesztelés
5 Integrációs tesztek
Az integrációs tesztek az egységteszteket követik. Az egység teszt szorosan kapcsolódik az
implementációs fázishoz, és biztosítja, hogy a részegységek önmagukban már helyesen
működnek. Így ha az integrációs tesztek során hibát észlelünk, az feltehetőleg a modulok
együttműködéséből adódik.
5-1
Szoftver tesztelés
A fenti iterációt addig folytatjuk, amíg a teljes rendszert összeépítettük, és azon valamennyi
teszt sikeresen lefutott.
Példa:
Figyeljük meg, hogy a kibővített rendszeren újra kell futtatnunk az előzőleg már sikeresen
lefutott teszteket is, hiszen nem lehetünk biztosak abban, hogy az újabb modulok
integrációja nem okoz hibát a korábbi modulok működésében. Ez a futtatandó tesztesetek
számának exponenciális növekedését jelenti, ami egy bonyolult rendszer esetén nagyon
erőforrás igényessé teszi a folyamatot.
Mivel a tesztelés tárgya mindig csak egy részrendszer, annak működtetéséhez tesztelési
környezetet kell biztosítani, ami segédkódok írását jelenti. A biztosítandó tesztelési
környezet attól függ, milyen integrációs módszert alkalmazunk. Elvben két lehetséges
megközelítés közül választhatunk:
• top-down integráció
• bottom-up integráció
5-2
Szoftver tesztelés
Folyamata:
Előnyei:
Hátrányai:
5-3
Szoftver tesztelés
Folyamata:
Bár a tesztelési munka még fejlesztő szervezeten belül folyik, szükséges az éles használat
környezetének minél pontosabb szimulációja.
5-4
Szoftver tesztelés
• Vizsgálni kell, hogy a rendszer adott időkorláton belül hogyan teljesít nagy
mennyiségű adatokon dolgozva.
• Intenzív feldolgozást kívánó helyzeteket kell teremteni, melyek szélsőségesek, de
előfordulhatnak.
• A robosztusság ellenőrzésére érdemes a terhelést olyan szintre is emelni, amely
(elvileg) a használat során nem fordulhat elő.
5.2.6 Teljesítménytesztelés
A teljesítmény vagy a hatékonyság mérése különböző terheléseknél és konfigurációkra
meghatározott válaszidők és feldolgozási sebességek formájában.
5.2.7 Konfigurációtesztelés
Különböző környezetek (hardver, operációs rendszer, egyéb szoftver installációk)
lehetségesek.
5-5
Szoftver tesztelés
5.2.9 Dokumentációtesztelés
Felhasználói és fejlesztési dokumentumokra egyaránt vonatkozik.
A használható tesztelési módszerek hasonlóak, mint a SLT esetén, de azok közül csak a
felhasználó számára releváns eseteket kell bemutatni.
Lehet verifikációs célja is (olyan hibák kimutatására, amelyek csak a végleges működtető
környezetben vizsgálhatók.)
Egy speciális UAT módszer a béta verzió kibocsátása. A béta verziót általában egy korlátozott
felhasználói kör kapja meg, akiktől elvárható, hogy az észlelt hibákat rendszeresen jelentik a
fejlesztőknek.
5-6
Szoftver tesztelés
Tartalomjegyzék
5-7
Szoftver tesztelés
6 Biztonsági tesztelés
Ez a fejezet áttekinti a biztonsági támadások leggyakoribb típusait. Az itt leírt biztonsági
támadások a www.owasp.org oldalon található szabad cikkek fordításai.
6-1
Szoftver tesztelés
A károsan felépített válasz hatása fölnagyítható, ha egy több felhasználó által használt web
cache tárolja vagy akár egyetlen egy felhasználó böngésző cache-e. Ha egy választ egy
megosztott web cache-ben tárolnak, mint például amik legtöbbször találhatóak a proxy
szerverekben, akkor a cache minden használója mindaddig a káros tartalmat fogja kapni,
amíg a cache bejegyzést ki nem tisztították. Ehhez hasonlóan, ha a választ egy egyéni
felhasználó böngészője cache-eli (tárolja), akkor az a felhasználó mindaddig a káros tartalmat
fogja kapni, amíg a cache bejegyzést meg nem tisztították, ebben az esetben csak a helyi
böngésző másolata lesz érintve.
Hogy egy ilyen támadás sikeres legyen, a támadónak a következőket kell tennie:
• Megtalálni a sebezhető service kódot, amin keresztül több fejléccel terhelheti meg a
http fejléc mezőjét.
• Rákényszeríteni a cache szervert, hogy flush-olja az aktuális cache tartalmat, amit
szeretnénk, hogy cache-eljen a szerver.
• Küldeni egy speciálisan elkészített kérelmet, amit a cache tárolni fog.
• Küldeni a következő kérelmet. A korábban befecskendezett, a cache-ben eltárolt
tartalom lesz a válasz erre a kérelemre.
6-2
Szoftver tesztelés
Példa:
Találtunk egy weblapot, ami a szolgáltatási nevét a „page” argumentumtól kapja, aztán
visszairányít (302) ehhez a kiszolgálóhoz.
pl.: http://testsite.com/redir.php?page=http://other.testsite.com/
A redir.php példa kódja:
rezos@dojo ~/public_html $ cat redir.php
<?php
header ("Location: " . $_GET['page']);
?>
6-3
Szoftver tesztelés
Szándékosan állítjuk be a jövő időt (a fejlécben 2009. október 27-re van állítva) a második
válasz HTTP fejléc „Last-Modified” mezőjében, hogy tároljuk a választ a cache-ben.
Ezt a hatást megkaphatjuk a következő fejlécek beállításával:
Last-Modified [Utoljára-Módosítva] (Az „If-Modified-Since” fejléc ellenőrzi)
ETag (Az „If-None-Match” fejléc ellenőrzi)
6.2.1 Leírás
A buffer túlcsordulás forrása a bevitt adat lehet. Amikor a bináris forrás file túltöltéssel
próbálkozik, a támadónak úgy kell módosítania/előkészítenie a bináris fájlt, hogy miután az
alkalmazás beolvasta, kiszolgáltatottá váljon egy klasszikus Buffer túlcsordulás támadásnak
(Buffer overflow attack). Az egyetlen különbség ez és a klasszikus típus között a bevitt adat
forrásában van. A leggyakoribb példák a különlegesen elkészített MP3, JPEG vagy ANI
fájlok, amik buffer túlcsordulást okoznak.
6.2.2 Példák
Az alkalmazás kiolvassa az első 8 karaktert a bináris fájlból.
rezos@dojo-labs ~/owasp/binary $ cat read_binary_file.c
6-4
Szoftver tesztelés
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *f;
char p[8];
char b[8];
f = fopen("file.bin", "r");
fread(b, sizeof(b), 1, f);
fclose(f);
strcpy(p, b);
printf("%s\n", p);
return 0;
}
6-5
Szoftver tesztelés
Azokat a függvényeket, amiknek nincs biztonságos verziójuk, át kell írni oly módon,
hogy tartalmazzanak biztonsági ellenőrzéseket. Az erre szánt idő meg fog térülni a
jövőben. Emlékezzen rá, hogy ezt csak egyszer kell megcsinálnia.
Olyan fordítókat kell használni, amik képesek azonosítani a nem biztonságos
függvényeket, logikai függvényeket és ellenőrzik, hogy a memória nincs-e átírva
olyan helyen, ahol nem szabadna.
6.3.1 Leírás
A fenyegető közeg a „támadók” egy olyan csoportja, ami támadást hajt végre. Lehetnek
emberi (szándékosak vagy szándékolatlanok) vagy természetes eredetűek (áradás, tűz, stb.).
1. A fenyegető közeg egy mondatos leírásával kezdődik.
2. Kik azok az emberek, akikből ez a fenyegetési közeg felépül?
3. Meg kell vitatni a fenyegető közeg jellemzőit.
6.4 Trójai
6.4.1 Leírás
A Trójai olyan program ami megbízható alkalmazásnak álcázva tartalmaz ártalmas kódot. Az
ártalmas kód lehet egyébként hasznos alkalmazás része, rejtőzhet egy elektronikus levél
hivatkozása mögött vagy el lehet rejtve JavaScript-et futtató oldalakon, hogy titkos
támadásokat intézzen sebezhető internet böngészők ellen.
További részleteket az Ember-a-böngésző-támadások-mögött (Man-in-the-browser attack)
című részben olvashat.
6.4.2 A Trójai 7 fő típusa
1. Távoli Hozzáférésű Trójai (Remote Access Trojan; RAT): Arra tervezték, hogy teljes
irányításd biztosítson a támadónak a fertőzött számítógép fölött. Ezt a Trójait általában
segédprogramnak álcázzák.
2. Adatküldő Trójai (Data Sending Trojan): Ez a fajta Trójai valamilyen
billentyűlenyomás-rögzítő (keylogger) technológiát használ, hogy értékes adatokra
6-6
Szoftver tesztelés
6.4.3 Tünetek
Néhány gyakori tünet:
A háttérkép vagy más háttérbeállítás magától megváltozik
Az egérmutató eltűnik
A programok maguktól betöltődnek és kilépnek
Állandóan furcsa figyelmeztető ablakok, üzenetek és kérdés dobozok jelennek meg
Az e-mail kliens magától leveleket küld mindenkinek a felhasználó címlistájára
A Windows magától leáll
A rendszer magától újraindul
Az internet hozzáférés adatai megváltoznak
A felhasználó ez irányú tevékenysége nélkül is nagy az internetkapcsolat terheltsége
A számítógép működése nagyon nagy erőforrásokat emészt fel (a számítógép lelassul)
A Ctrl + Alt + Del gombkombináció nem működik
6.5.1 Leírás
Egy account kizárási támadáskor a behatoló megpróbálja kizárni az összes felhasználói
accountot, általában oly módon, hogy több alkalommal hibás bejelentkezést produkál, mint
amennyi a bejelentkeztető rendszer tűréshatára. Ha például egy felhasználó három hibás
bejelentkezési próbálkozással zárja ki az account-ját a rendszerből, akkor a támadó nemes
egyszerűséggel úgy zárja ki az account-jaikat, hogy háromszor hibás hibás bejelentkezést
produkál. Ez a fajta támadás nagymértékű szolgáltatás-megtagadási támadást eredményezhet,
ha minden felhasználói account ki van zárva, főként akkor, ha az accountok visszaállítása
komoly mennyiségű munkát igényel.
6-7
Szoftver tesztelés
6.6.1 Leírás
A közvetlen statikus kód befecskendezése általi támadás abból áll, hogy a kódot közvetlenül
az alkalmazás által használt erőforrásba juttatják bele, miközben egy felhasználó kérelme
éppen feldolgozás alatt van. Ez általában úgy történik, hogy befolyásolják a könyvtár és
sémafájlokat, amik a felhasználói kérelemnek megfelelően lettek létrehozva az adatok
megfelelő megválasztása nélkül. Egy, a módosított erőforráshoz beérkező felhasználói
kérelem esetén a benne foglalt cselekvés végrehajtódik a szerveroldalon a web szerver
folyamatának a függvényében.
A szerver oldali beszúrás (Server Side Includes) egy típusa a közvetlen statikus kód
befecskendezésének. Ez nem összekeverendő a többi fajta kód befecskendezéssel, mint
amilyen az XSS („Kereszt-helyszíni szkriptelés” vagy „HTML befecskendezés”), aminél a
kód a kliens oldalán hajtódik végre.
6.6.2 Példák
Példa 1
Ez az egyszerű példa a CGISCRIPT.NET csSearch 2.3 egyik gyengeségének a kihasználását
mutatja be, amit a Bugtraq-on jelentettek meg, 4368-as azonosítószám alatt. A következő
URL szerverre való meghívásával lehetséges a ‘’’’setup’’’ változóban meghatározott
parancsokat végrehajtani.
csSearch.cgi?command=savesetup&setup=PERL_CODE_HERE
A klasszikus példa szerint a következő parancsot arra lehet használni, hogy minden fájlt
eltávolítsunk a “/” könyvtárból:
csSearch.cgi?command=savesetup&setup=`rm%20-rf%20/`
Tegyük hozzá, hogy a fönti parancsnak kódolva kell lennie, hogy elfogadható legyen.
Példa 2
Ez a példa egy, az Ultimate PHP Board (UPB) 1.9 (CVE-2003-0395)-ben lévő sebezhető
pontot használ ki, lehetővé téve a támadónak, hogy véletlenszerűen futtasson php kódokat.
Mindezt azért teszi, mert néhány, a felhasználóhoz tartozó változó, mint például az IP-cím
vagy a User-Agent egy olyan fájlban tárolódnak, amit az admin_iplog.php oldal használ, hogy
felhasználói statisztikákat mutasson. Amikor egy adminisztrátor ezt a lapot használja, akkor a
korábban egy káros kérelem által befecskendezett kód végrehajtódik. A következő példa egy
ártalmas php kódot tartalmaz, ami belerondít az index.php lapba, amikor az adminisztrátor az
admin_iplog.php-t futtatja.
6-8
Szoftver tesztelés
6.7.1 Áttekintés
Az „útkeresztezési támadások” olyan fájlok és könyvtárak elérését célozzák, amik a hálózati
gyökér (web root) könyvtáron kívül vannak eltárolva. Az alkalmazás böngészése közben a
támadó olyan közvetlen hivatkozásokat keres, ami a web szerveren tárolt fájlokra mutatnak. A
„ ../ ” sorozatot és változóit tartalmazó fájlok manipulálásával lehetséges lehet tetszőleges
olyan fájlhoz vagy könyvtárhoz hozzáférni, ami a fájlrendszerben van tárolva, beleértve az
alkalmazások forráskódjait , konfigurációs- és a rendszer működése szempontjából kritikus
egyéb fájlokat, amit csak a rendszer hozzáférési műveletek korlátoznak. A támadó “../”
sorozatokat használ, hogy följebb lépjen a gyökérkönyvtárba és így lehetővé tegye a
fájlrendszerben való mozgást.
Ezt a támadást egy olyan külső ártalmas kód befecskendezésével lehet kivitelezni, ami a
Resource Ijection (Forrás befecskendezés) támadástípus által kitaposott ösvényt használja. A
támadás kivitelezéséhez nem szükséges különleges eszközök használata; a behatoló általában
valamilyen internetes fürkészt (web spider/crawler) használ, hogy felderítse az összes
használható URL-t.
Ezt a támadást több néven is ismerik, például:
“dot-dot-slash” („pont-pont-vesszőcske”)
“directory traversal” („könyvtárkeresztezés”)
“directory climbing”(„könyvtármászás”)
“backtracking” („visszakövetés”).
6.7.2 Leírás
Kérelem változatok
Kódolás és dupla kódolás:
%2e%2e%2f jelentése ../
%2e%2e/ jelentése ../
..%2f jelentése ../
%2e%2e%5c jelentése ..\
%2e%2e\ jelentése ..\
..%5c jelentése ..\
%252e%252e%255c jelentése ..\
..%255c jelentése ..\
és így tovább...
„Százalékos kódolás (más néven URL kódolás)” (Percent encoding (aka URL encoding))
Megjegyzés: a web tárolók egy szintnyi kódolást hajtanak végre a form-okról és az URL-ekről
származó százalékosan kódolt értékeken.
..%c0%af jelentése ../
6-9
Szoftver tesztelés
A legtöbb operációs rendszerben null bájtokat (%00) lehet injektálni a fájlnév lezárása
céljából. Például a következő paraméter elküldése:
?file=secret.doc%00.pdf
azt eredményezi, hogy a Java alkalmazás úgy látja, hogy a sztring „.pdf”-el ér véget, míg az
operációs rendszer úgy látja, hogy a fájl végén ".doc" áll. A támadók ezt a trükköt arra
használhatják, hogy átjussanak az érvényesítő rutinon.
6.7.3 Példák
Példa 1
A következő példa megmutatja, hogy az alkalmazás hogyan bánik a használatban lévő
erőforrásokkal:
http://some_site.com.br/get-files.jsp?file=report.pdf
http://some_site.com.br/get-page.php?home=aaa.html
http://some_site.com.br/some-page.asp?page=index.html
Ebben a példában lehetséges olyan ártalmas sztringet beilleszteni, mint változó paramétert,
hogy hozzáférjünk a webes könyvtáron kívüli fájlokhoz.
http://some_site.com.br/get-files?file=../../../../some dir/some file
6-10
Szoftver tesztelés
Példa 3
Ez a példa azt az esetet mutatja be, mikor a támadó arra kényszerítette a szervert, hogy
megmutassa a CGI forráskódot.
http://vulnerable-page.org/cgi-bin/main.cgi?file=main.cgi
Példa 4
Ez a példa a Wikipedia - Directory Traversal oldalról lett továbbgöngyölítve
A sebezhető alkalmazás kódjának tipikus példája:
<?php
$template = 'blue.php';
if ( is_set( $_COOKIE['TEMPLATE'] ) )
$template = $_COOKIE['TEMPLATE'];
include ( "/home/users/phpguru/templates/" . $template );
?>
Ez ellen a rendszer ellen a következő HTTP kérelmet lehet támadásként használni:
GET /vulnerable.php HTTP/1.0
Cookie: TEMPLATE=../../../../../../../../../etc/passwd
A következő szerver választ generáljuk:
HTTP/1.0 200 OK
Content-Type: text/html
Server: Apache
root:fi3sED95ibqR6:0:1:System Operator:/:/bin/ksh
daemon:*:1:1::/tmp:
phpguru:f8fk3j1OIf31.:182:100:Developer:/home/users/phpguru/:/bin/csh
Az ismételt ../ karakterek a /home/users/phpguru/templates/ után azt okozták, hogy
a include() átkerüljön a gyökérkönyvtárba és tartalmazza az /etc/passwd UNIX jelszó fájlt.
A UNIX etc/passwd egy szokásos fájl arra, hogy bemutassuk a directory traversal-t, mivel a
számítógépes kalózok gyakran használják arra, hogy jelszavakat törjenek fel.
Amikor a web szerver a webes alkalmazás hibáit tartalmazó információval tér vissza, akkor a
támadónak sokkal egyszerűbb kitalálni a pontos helyet (vagyis a forráskódot tartalmazó
fájlhoz vezető utat, amit aztán megjeleníthet).
6.8.1 Leírás
Ezzel a fajta támadással a behatoló megpróbálja úgy megkerülni a biztonsági
mechanizmusokat, hogy nagyon kevés információval rendelkezik róluk. A következő módok
valamelyikét használhatja:
könyvtár támadás (mutációkkal vagy anélkül) (dictionary attack (with or without mutations))
nyers-erő támadás (megadott csoportú karakterekkel, például: alfanumerikus, különleges,
„case-sensitive”) (brute-force attack )
A támadó megpróbálja elérni a célját. A megfelelő paraméterek (egy bizonyos módszer, a
próbálkozások száma, a rendszer hatékonysága) figyelembe vételével, amik levezénylik a
támadást a behatoló megjósolhatja, hogy meddig kell tartania a támadásnak. A nem nyers-erő
támadások (non brute-force attacks), amikben mindenféle karakter szerepel, nem
kecsegtetnek biztos sikerrel.
6.8.2 Példák
A Nyers-erő támadásokat leginkább arra használják, hogy megtippeljék a jelszavakat és
megkerüljék a hozzáférési ellenőrzéseket. Mindemellett sok olyan eszköz van, amik ezt a
technológiát használják, hogy a támadó részéről hasznosnak vélt információkat gyűjtsenek ki
bizonyos web szolgáltatások katalógusaiból. Nagyon sok esetben a támadások célpontjai a
különböző formátumokban lévő adatok (GET/POST) és a felhasználói Session-ID-k.
Példa 1
Az első forgatókönyvben, ahol az a Nyers-erő célja, hogy megtudjuk a jelszót kódolatlan
formában. Úgy tűnik, hogy a John the Ripper egy nagyon hasznos eszköz. A 10 legjobb
jelszótörő különböző módszerekkel, többek között Nyers-erővel dolgoznak. Ezek
megtalálható az alábbi oldalon:
http://sectools.org/crackers.html
A web szolgáltatások tesztelésére a következő eszközök állnak rendelkezésre:
dirb (http://sourceforge.net/projects/dirb/)
WebRoot (http://www.cirt.dk/tools/webroot/WebRoot.txt)
A dirb-höz fejlettebb eszközök is tartoznak. A segítségével képesek lehetünk:
cooky-kat beállítani
bármilyen HTTP fejlécet hozzáadni
PROXY-t használni
megtalált objektumokat mutálni
http(s) kapcsolatokat tesztelni
katalógusokban és fájlokban keresni meghatározott könyvtárak és sémák segítségével
és még ezeknél sokkal többre is
6-12
Szoftver tesztelés
-----------------
Generating Wordlist...
Generated Words: 839
oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00
o Webserver Bruteforcing 1.8 o
0 ************* !!! WARNING !!! ************ 0
0 ******* FOR PENETRATION USE ONLY ********* 0
0 ****************************************** 0
o (c)2007 by Dennis Rand - CIRT.DK o
oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00
6.8.4.1 Leírás
HTTP válasz elosztás (HTTP response splitting) történik, amikor:
Adat kerül a webes alkalmazásba rendezetlen forráson keresztül, ami legtöbbször egy
HTTP kérelem.
Az adat egy HTTP válasz fejlécben szerepel, amit egy web használónak küldtek
anélkül, hogy a káros karaktereket ellenőrzése megtörtént volna.
A „HTTP response splitting” a befejezés egy módja, nem pedig a befejezés maga. Alapjaiban
véve a támadás meglehetősen egyszerű: a támadó káros adatot továbbít egy sebezhető
alkalmazásnak, az alkalmazás pedig beleteszi az adatot a HTTP válasz fejlécébe.
A sikeres támadás érdekében, az alkalmazásnak engedélyeznie kell az olyan adatbevitelt, ami
CR (carriage return, %0d vagy \r) és LF (line feed, %0a vagy \n) karaktereket is beenged a
fejlécbe. Ezek a karakterek nem csak irányítást adnak a támadónak az alkalmazás által
küldeni szándékozott válasz maradék fejléce és főrésze fölött, de azt is lehetővé teszik, hogy
újabb, teljesen az irányítása alatt lévő válaszokat adjon.
6-14
Szoftver tesztelés
6.8.4.2 Példák
A következő kódrészlet kiolvassa egy weblog szerzőjének a nevét egy HTTP kérelemből és
cookie fejlécként beállítja egy HTTP válaszban.
String author = request.getParameter(AUTHOR_PARAM);
...
Cookie cookie = new Cookie("author", author);
cookie.setMaxAge(cookieExpiration);
response.addCookie(cookie);
HTTP/1.1 200 OK
...
Nyilvánvaló, hogy a második választ teljesen a támadó irányítja, olyan tartalmú fejlécet és
törzset ad neki, amilyet szeretne. Az, hogy a támadó olyan HTTP választ generál, amit akar,
lehetővé tesz több más fajta támadást is, többek között a következőket:
Cross-User Defacement, Cache Poisoning, Cross-site Scripting (XSS) és Page Hijacking.
6.9.1 Leírás
A támadó arra kényszeríti az áldozatot, hogy több erőforrást használjon, mint amennyi a
támadó hozzáférési szintjével engedélyezve van. A program valószínűleg nem, vagy csak
hibásan szabadítja föl a rendszer egy erőforrását. Az erőforrás nem lett rendesen kiürítve és
előkészítve az újbóli felhasználásra.
6.9.2 PÉLDÁK
Példa 1
A következő metódus sosem fogja bezárni a saját maga által megnyitott fájl kezelőt/számlálót
(file handle). The method for A StreamReader Finalize() metódusa végül meghívja a Close()
metódust, de semmi sem tudja megmondani, hogy mennyi időbe fog telni, mielőtt a Finalize()
6-15
Szoftver tesztelés
működésbe lépne. Valójában semmi garancia nincs arra, hogy a Finalize() egyáltalán
működésbe fog lépni. Egy terhelt környezetben ez azt eredményezheti, hogy a VM
felhasználja az összes rendelkezésére álló fájl számlálót.
private void processFile(string fName) {
StreamWriter sw = new
StreamWriter(fName);
string line;
while ((line = sr.ReadLine()) != null) processLine(line);
}
Miután minden fájl számlálót (fájl leírót) felhasznált, a VM nagyon instabillá válhat,
lelassulhat, vagy determinisztikusan megszakíthatja a működést a korábbi állapotához képest.
Példa 2
Normál körülmények között az alábbi C# kód egy adatbázis lekérdezést hajt végre,
feldolgozza a az adatbázis által adott eredményt és bezárja a hozzá társított SqlConnection
objektumot. De ha egy kivétel történik az SQL vagy az eredmények feldolgozása közben,
akkor az SqlConnection objektum fog bezáródni. Ha ez elég sokszor megtörténik, akkor az
adatbázis ki fog futni a rendelkezésére álló kurzorokból és nem fog tudni több SQL
lekérdezést végrehajtani.
C# példa:
...
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(queryString);
cmd.Connection = conn; conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
HarvestResults(rdr);
conn.Connection.Close();
...
6.10.1 Leírás
A kémprogram (Spyware) olyan alkalmazás, ami statisztikai adatokat gyűjt a felhasználó
számítógépéről és továbbküldi azt az interneten a felhasználó beleegyezése nélkül. Ezeket az
információkat általában a cookie-kból vagy a böngésző Előzményeiből (history) gyűjti ki. A
kémprogramok akár más programokat is telepíthetnek, reklámokat jeleníthetnek meg vagy
6-16
Szoftver tesztelés
6.11.1 Leírás
A Hálózati Lehallgatás (Network Eavesdropping) vagy más néven hálózati szimatolás
(network sniffing) egy olyan hálózati réteg támadás, ami azt a célt szolgálja, hogy csomagokat
fogjunk el a hálózatban, ami mások számítógépéről származik és az ebben lévő adatokban
olyan kényes információkat találjunk, mint a jelszavak, session tokenek vagy bármilyen nemű
titkos információ.
Ezt a támadást a „hálózati szimatoló”-knak (network sniffer) nevezett eszközökkel lehet
kivitelezni. Ezek az eszközök csomagokat gyűjtenek a hálózaton és az eszköz minőségétől
függően a protokoll dekóderekhez vagy a stream újraillesztőkhöz hasonlóan analizálják a
begyűjtött adatokat.
A hálózat környezetére néhány feltételnek teljesülnie kell, hogy a szimatolás hatékony legyen:
• LAN környezet HUB-okkal (LAN + HUB).
Ez az ideális eset, mivel a HUB egy hálózati ismétlő eszköz, ami duplikál minden, akármelyik
porton keresztül érkezett hálózati keretet, így a támadás nagyon egyszerűen kivitelezhető,
mivel más feltételeknek nem is kell megfelelni.
• LAN környezet kapcsolókkal (LAN + SWITCH)
Hogy a hallgatózás eredményes legyen, egy előzetes feltételnek teljesülnie kell. Mivel a
switch alapesetben csak egy keretet küld a portnak, szükségünk van egy olyan
mechanizmusra, ami duplikálja vagy átirányítja a hálózati csomagokat a rosszindulatú
rendszer részére. Például ahhoz, hogy duplikáljuk a forgalmat egyik portról a másikra, egy
különleges beállításra lesz szükségünk a switch-ben. Hogy átirányítsuk a támadást egyik
portról a másikra, szükségünk lesz egy előzőleges kihasználásra, mint például az arp spoof
támadás. Ebben a támadásban a rosszindulatú rendszer útválasztóként (router) működik az
áldozatok közötti kommunikációban, lehetővé téve azt, hogy „kiszimatoljuk” a felcserélt
csomagokat.
• WAN környezet
6-17
Szoftver tesztelés
Ebben az esetben, a hálózati „szimatolás” sikeréhez arra van szükség, hogy rosszindulatú
rendszer útválasztóként (router) működjön a kliens és a szerver közötti kommunikációban
Ezen hiba kihasználásának egyik módja, ha DNS áltámadást indítunk a kliens rendszer ellen.
A „Hálózati Lehallgatás” egy passzív támadás, amit nagyon nehéz felfedezni. Fölfedezhető a
megelőző állapot hatásából vagy néhány esetben rábírhatjuk a rosszindulatú szervert, hogy
válaszoljon egy olyan hamis kérelemre, amit a rosszindulatú rendszer IP címére küldtünk, de
egy másik rendszer MAC címével.
6.11.2 PÉLDÁK
Amikor a HUB elnevezésű hálózati eszközt használunk egy Helyi Hálózat topológiájában,
akkor a „Hálózati Lehallgatás” kivitelezése sokkal könnyebbé válik, mivel az eszköz
mindenféle, egy porton bejövő adatforgalmat duplikál az összes többi portra. Egy protokoll
elemzőt (protocol analyzer) használva a támadó a LAN egész adatforgalmára ráteheti a kezét
és így kényes információkat szerezhet meg.
6.12.1 Áttekintés
A „CSRF” egy olyan támadás, ami arra kényszeríti a felhasználót, hogy olyan tevékenységet
végezzen egy webes alkalmazásban, amibe éppen be van jelentkezve, amit nem állna
szándékában megtenni. Egy kis „szocializációs mérnökösködéssel” (például hivatkozás
küldése e-mailen vagy chat-en keresztül) a támadó arra kényszeríti a felhasználót, hogy olyan
cselekedeteket hajtson végre, amiket a behatoló szeretne. Egy mezei felhasználó esetében egy
sikeres CSRF támadás veszélybe sodorhatja a felhasználó adatait és tevékenységét. Ha a
támadással megcélzott azonosító egy adminisztrátorhoz tartozik, akkor egy ilyen behatolás az
egész webes alkalmazás biztonságát veszélyezteti.
6.13 Vonatkozó biztonsági intézkedések
6.13.1 Hogyan nézzünk át egy kódot CSRF sebezhetőséget keresve?
A OWASP Code Review Guide cikkben olvashatunk arról, hogy hogyan nézzünk át egy
kódot CSRF sebezhetőség reményében (Reviewing code for CSRF).
6.13.2 Hogyan teszteljük a CSRF sebezhetőséget?
A OWASP Testing Guide cikkben olvashatunk arról, hogy hogyan teszteljük a CSRF
sebezhetőséget (Test for CSRF).
6.13.3 Hogyan előzzük meg a CSRF sebezhetőséget?
A OWASP CSRF Prevention Cheat Sheet dokumentumban olvashatunk a sebezhetőség
megelőzéséről.
Halgassuk meg a következő felvételt: OWASP Top Ten CSRF Podcast.
Egy kiváló írás John Melton tollából arról, hogy hogyan használjuk az OWASP ESAPI
beépített anti-CSRF funkcióját: excellent blog post
6.13.4 Leírás
Az „oldalakon keresztüli kérelem hamisítás” (CSRF) egy olyan támadás, ami trükkös módon
ráveszi az áldozatot, hogy olyan weboldalt nyisson meg, ami káros kérelmet tartalmaz. Ez
olyan értelemben káros, hogy örökli az áldozat személyazonosságát és privilégiumait és
ezekkel felszerelve az áldozat nevében nem kívánt tevékenységet végez, mint például
megváltoztatja az e-mail címet, a lakáscímet, a különféle jelszavakat vagy éppen vásárol
valamit. A CSRF támadások általában olyan funkciókat céloznak, amelyek valamilyen
6-18
Szoftver tesztelés
6.13.6 PÉLDÁK
Hogyan működik a támadás?
Számos módja van annak, hogy trükkel rávegyük a felhasználót, hogy töltsön be vagy küldjön
információt egy webes alkalmazásból/ba. A támadás kivitelezése céljából először azt kell
6-19
Szoftver tesztelés
átlátnunk, hogyan hozzunk létre olyan káros kérelmet, amit az áldozat végre fog hajtani.
Vegyük szemügyre a következő példát: Aliz 100 dollárt szeretne utalni Robinak a bank.com
oldalon keresztül. Az Aliz által generált kérelem nagyjából a következőképpen fog kinézni:
POST http://bank.com/transfer.do HTTP/1.1
...
...
...
Content-Length: 19;
acct=BOB&amount=100
Mária úgy dönt, hogy kihasználja a webes alkalmazás eme gyenge pontját és Aliz lesz az
áldozata. Először is Mária megszerkeszti a következő URL-t, ami át fog utalni 100000 dollárt
Aliz számlájáról az övére:
http://bank.com/transfer.do?acct=MARIA&amount=100000
Most hogy a káros kérelme elkészült, Máriának trükkel rá kell vennie Alizt, hogy elküldje azt.
A legalapvetőbb módja ennek az, hogy küld Aliznak egy HTML e-mailt, ami a következőket
tartalmazza:
<a href="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my
Pictures!</a>
Ha ezt a kép tag-et beleteszi az email-be, akkor Aliz csak azt fogja látni, hogy egy kis doboz
jelenik meg, mintha a böngésző nem tudta volna feldolgozni a képet. Azonban a böngésző
ETTŐL FÜGGETLENÜL elküldi a kérelmet a bank.com oldalnak anélkül, hogy a
tranzakciónak bármilyen látható jele lett volna.
6-20
Szoftver tesztelés
Tartalomjegyzék
6 Biztonsági tesztelés ................................................................................. ........................ 6-1
6.1.1 Működés ellehetetlenítése – Cache Mérgezés ................................................. 6-2
6.2 Adatszerkezet támadás - Bináris forrás fájl túltöltése.............................................. 6-4
6.2.1 Leírás ............................................ ................................................... .................. 6-4
6.2.2 Példák ............................................ ................................................... ................. 6-4
6.3 Kártékony kód beágyazása – Logikai/Időzített bomba............................................. 6-6
6.3.1 Leírás ............................................ ................................................... .................. 6-6
6.3.2 Kockázati tényezők ................................................................................... ......... 6-6
6.4 Trójai ............................................ ................................................... .......................... 6-6
6.4.1 Leírás ............................................ ................................................... .................. 6-6
6.4.2 A Trójai 7 fő típusa ................................................................................. ........... 6-6
6.4.3 Tünetek........................................... ................................................... ................ 6-7
6.4.4 Kockázati tényezők ................................................................................... ......... 6-7
6.5 Azonosítási folyamat kihasználása – Account kizárási támadás .............................. 6-7
6.5.1 Leírás ............................................ ................................................... .................. 6-7
6.5.2 Például: eBay támadás ................................................................................ ...... 6-8
6.6 Befecskendezés – Közvetlen statikus kód befecskendezése .................................... 6-8
6.6.1 Leírás ............................................ ................................................... .................. 6-8
6.6.2 Példák ............................................ ................................................... ................. 6-8
Példa 1 ........................................... ................................................... ............................... 6-8
Példa 2 ........................................... ................................................... ............................... 6-8
6.7 „Útkeresztezési támadás” (Path Traversal Attack) ................................................. . 6-9
6.7.1 Áttekintés ........................................................................................... ............... 6-9
6.7.2 Leírás ............................................ ................................................... .................. 6-9
Kérelem változatok................................................................................... ........................... 6-9
6.7.3 Példák ............................................ ................................................... ............... 6-10
Példa 1 ........................................... ................................................... ............................. 6-10
Példa 2 ........................................... ................................................... ............................. 6-10
Példa 3 ........................................... ................................................... ............................. 6-11
Példa 4 ........................................... ................................................... ............................. 6-11
6.7.4 „Abszolút útkeresztezés” (Absolute Path Traversal)....................................... 6-11
6-21
Szoftver tesztelés
6-22
Szoftver tesztelés
6-23
Szoftver tesztelés
7 Teszt menedzsment
A tesztelési tevékenység a fejlesztési folyamat szerves része. A tesztelés helyét a fejlesztési
folyamatban a V modell szemlélteti.
Teszt tervezés
Konfiguráció menedzsment
Kockázatok és a tesztelés
Incidens menedzsment
• Az incidens fogalma.
7-1
Szoftver tesztelés
7-2
Szoftver tesztelés
Egy független tesztelő több más jellegű hibát vehet észre, mint aki a programozókkal együtt
dolgozik, vagy maga is programozó, mivel más rálátása lehet a projektre, illetve észrevehet
olyan problémákat is, amik a fejlesztő csapat gondolkodásmódjából erednek. Valamint egy
független tesztelő, aki a vezetői menedzsernek írja jelentéseit, őszinte tud maradni, hiszen
nem kell annak negatív következményeivel számolnia, hogy munkatársait bírálja, vagy
menedzsere munkájának hibáira mutat rá. Egy független tesztcsapat rendelkezhet
elkülönített költségvetéssel és vezetéssel, így annak tagjai is nagyobb eséllyel pályázhatnak
majd jobb munkahelyi pozíciókra, hiszen nincsenek a programozók alá vagy mellé rendelve.
A független tesztcsapat hátránya lehet viszont a projekttől vagy annak részeitől való
elszigetelődés. Ha a tesztelő ismeri az adott programozók általános gondolkodásmódját,
nagyobb eséllyel fedezi fel annak hibáit. Rosszabb esetekben előfordulhat az is, hogy a
projektet nem teljesen ismerve túlzott figyelmet szentelnek annak bizonyos részegységei
hibáinak feltárására, így más jellegűeket elhanyagolhatnak. Ez a kommunikációs probléma
ellenszenvhez, elidegenedéshez, vádaskodáshoz vezethet.
Gyakori eset, hogy a vállalatok vágyva a független tesztelés előnyeire csak azért hoznak létre
ilyen csapatokat, hogy hogy hamarosan feloszlassák őket. Oka, lehet, hogy a tesztmenedzser
sikertelen a fenti problémák hatékony kezelésében.
A tesztelés függetlenségének megállapításához tehát nem létezik egyedüli helyes út. Minden
egyes projekthez, a projekt alkalmazási területét, kockázatszintjét, komplexitását figyelembe
véve kell döntenünk. Lehetséges természetesen a projekt előrehaladásával annak különböző
szintjein változtatnunk a tesztcsapat függetlenségén és összetételén. Vannak tesztek, amiket
célszerűbb, a mások végeznek el, más területek szakértői a projekt tárgyától függően.
Valószínűleg a teszt végrehajtás megkezdése előtt nem lesz szükség a tesztelők munkájára,
de érdemes őket már a projekt indulásakor alkalmazni. A tesztelés tervezési és előkészítési
időszakában a tesztelőknek meg kell ismerniük a teszttervet, és közre kell működniük annak
esetleges javításában, meg kell ismerniük a követelményeket, és a műszaki tesztterv-
specifikációk elemzését. Gyakran a tesztelők állítják be a tesztkörnyezetet, vagy ők segítik
ebben a rendszeradminisztrátorokat. A tesztek megkezdésével első feladatuk a tesztek
tesztkörnyezetbe való implementálása. A tesztfolyamat során a tesztelők hajtják végre és
naplózzák a teszteket, majd kiértékelik és elemzik azokat.
Fontos, hogy a tesztelő megértse az adott szoftver működésének lényegét, így felismerje az
azzal szemben támasztott elvárásokat, így megtalálja a kiemelt fontosságú, kritikus pontokat.
Technológia
Tesztelés
7-4
Szoftver tesztelés
Ha teszt tervet készítünk, érdemes sablont használnunk, így nehezebben felejtünk ki kritikus
pontokat. Használható az IEEE 829-es sablon. Ezen sablon alapján egy teszttervnek a
következőket kell tartalmaznia:
1. Tesztterv azonosító
2. Bevezető
3. Tesztegységek
A tesztelés tárgyának a meghatározása. Tartalmazhat hivatkozásokat más
dokumentációkra, például rendszer tervekre.
4. Tesztelendő funkciók
A tesztelés céljának meghatározása (funkciók, nem funkcionális követelmények).
5. Nem tesztelendő funkciók
Olyan követelmények, amelyeket nem szükséges, vagy nem lehetséges tesztelni.
6. Szemléletmód
7-5
Szoftver tesztelés
A tesztterv írásának célja, hogy végiggondoljuk a teszt menetét, hisz amit végiggondolva
képesek vagyunk szóba foglalni, azt értjük is. Egy jó tesztterv rövid és lényegre törő, így
megírása nem egyszerű feladat. Magas szinten át kell gondolnunk a tesztelési munka célját.
Ehhez meg kell határoznunk, hogy mi tartozik az adott teszthez, és mi nem, meg kell
értenünk a termékkockázatokat és ismernünk kell a teszttelés lehetséges korlátait (például
anyagi vagy időkorlát). Ezek után fel kell osztanunk a feladatokat, a tesztelés különböző
szintjeire. Ezután egyeztetnünk kell a szintek közti átmeneteket, majd meghatároznunk, hogy
mely információkat kell átadnunk a teszt végén a karbantartó csapatnak. Ehhez meg kell
határoznunk, hogy milyen állítások lennének igazak egy olyan projektre, amin sikeresen
elvégezték a tesztelést, azaz specifikálnunk kell minden teszt esetén annak belépési és
kilépési feltételeit.
7-6
Szoftver tesztelés
7-7
Szoftver tesztelés
Lehetséges tevékenységei:
• Átértékeli a tesztek prioritásait, ha úgy látja, hogy előre nem látható kockázatok
léptek fel.
• Megváltoztatja a teszt ütemtervet.
• Megváltoztatja a teszt kritériumokat,a megváltozott prioritásokhoz igazítva.
• Átértékeli a termék kockázatokat, és ennek megfelelően módosítja a tesztelési tervet.
• Egyes kevésbé fontos funkciókat ki kell venni a követelmény listából, hogy a határidőt
tartani lehessen.
• Módosítani kell az átadási határidőt, hogy a még szükséges tesztelési
tevékenységeket végre lehessen hajtani.
• Át lehet adni a rendszert, de a felhasználóval tudatni kell, hogy bizonyos funkciók
még nem lettek alaposan tesztelve. Ilyenkor az üzemszerű használat mellett
folytatódhat a tesztelés. Ez abban az esetben lehet alternatíva, ha a gyengén tesztelt
funkciók a gyakorlatban ritkán fordulnak elő.
Az incidens kezelés az IEEE 1044 (Standard Classification for Software Anomalies) szabvány
szerint: „ A specifikációtól eltérő viselkedés felismerése, megvizsgálása, és az elhárítására
tett intézkedések együttese.”
Az incidensek jelentése a tesztelési folyamat során igen gyakori tevékenység. Eszköze lehet
egy telefonhívás, egy feljegyzés, egy e-mail. Ezeknek az ad-hoc eszközöknek az előnye az
egyszerűség és a gyorsaság, de hátrányuk, hogy a jelentésnek nem marad nyoma, és a
megoldás státusza nem követhető. Ezért az incidensek jelentésére célszerű valamilyen erre a
célra dedikált szoftvert használni. Ezek az eszközök az incidens jelentésétől annak
megoldásáig képesek követni a folyamatokat. Erre alkalmas eszközökre a jegyzet későbbi
fejezetébe láthatunk példát.
7-8
Szoftver tesztelés
7-9
Szoftver tesztelés
Tartalomjegyzék
7-10
123456709
656
535
5656
3535
733
3
3
56
3
63
!"53
9#534326$#65673
3
3
6
523
355%&65359'63
3
36
567&6(65
35656
66
66(26565
6
6265
63%6
23
!7)66569
'63
3
35656
663326
)66
67667
236
6567*5765656556
&6"5)565656
%55359$6567
6)
67623
235!5653
3
33)666
265
235)9+6"56
73%%6
656656265&3676()6659
$#6567
,)'63
3
356726
65656
2646
%567763
2336
33(575776(6
676'66
%6
6
66(6
6
5556676339
+56726
6565653
3
372656
6
67563)"
5
%77!(-%5676656766(6
335.2)6%65265
2)
6(73/52)3.
53
326
)56
6
/6"7
&3&55656
&659,63%6&66565356726
65656
6
(353432647&65$#65676*3
3
35535&69
$#656736)6
72653
6%
536
(90
1$2313(35
%77$33&6556726
65656
763
3
39
$#6567
)36566
76(6
66
)66"56
3
!67*6
235&3%6
23
!356
53
&5656
56
764
095
676.7("5/4("56"56
6265 33%6
23
!76
6
565565359$#6567535&33
53("55.3765553
6
565/353
5676546*("55.46765537/3-)
53
65
667*("556
)6
'6
(3
3
!
65
667*
%73
3
235!9
8959157
676.9367
/47623&5%
)335567
9
:956756.;
"5/4'667675
3763(35356
679
<95=
147>)67676.=
012341562489
482
1012342
45641
3821411
1413!
"85821855#482
614!115$
%&91'(&6)$114*4+854
34551*1*231,412341214
65-.14%41.
'1519/2-6.191215113!14-
*62!*11914.+/534143
4
0%&91
"01.2'(13851389)$61+4822
8"15238542
23852389.123851*4
8"1523852"151591-915*1
1*.1+,51+4+8612
4
31.154"15.4
4
%39451
.'(6.!3)$1411*%41.
'.582
1*
23854.#415-62"
5*942
81*1514121.#4+1537+23854
8.!386251541462215-9#151962385238988591.
4499
985264614
:%;
<
4'(6296456211389)$64491.42-
*%41.
'
51!"
858*23
"442251
3381.154151911435185
5#4821*=%
11'(64151)5114!261485234+-41234156241
151914.."444+7+627+%41.
'-9#5119855#4+
>%11.51'(?41913!)$3.582621"1+1362.8498462.!
4+8485
5#44+165*1
191556331551855#4
=65.8523852389840@@(0@@2395854"1523852)-3.!34
1*982
.116232964562123898401855#4+(9.166264231
1/515/5.621)-
2231216*23836624"
51/5.131233-
9!50@@0@@3151*.!1"
.5
012341562489
482
315311
338
4441
151914
238541
8
16
954441591!5348
"9519#00$%1&12491!
4
485234
5
55155#00$%1&12415191485234
55'
151151913153165(223141441
858215
)316123111855*482
6141159151(3!568
1514621585+1626164159,1855*482
-
.$
4
/
50$
4
551-2461#00$#00$"5114
3414
04+2311-#00$66265238549+231918205)0
$6"0#)7$806$096:"7);)0)0%<)1=1559382
412341562665854585)0$6"09+2314238564
554+5!1
>$40?4
51-4123415*84
558%9'108125%12
/191'
4115)09+231121461964111406585-@1A141119
11913115591
B
55
C%11/420D4*8*4821-C1231121/852#00$85234'
422391519828%;'18*4C1(62340#04;
62164*2E44595155146411(6238545815'
2385+854562311141451!5(143848*4824D5458116'
5133!
F821G11510G/2
54144821-514(C1231162
(623489
4
(34!56/2
54123
91
3
5942311852391613(623(3191
(19614483433
(6234561312'
1451124
866216161011'51/2
54101156212
412341562121461619121345114261485234
H"1$91412C441%1&1240$964111-5)062$6"0
96411145114913)/
1
235
151314!
616236461155'1#00$+
58245593$65853I41
6223+(3+
58223!261239/51)&52
235
151314!
3
41214523+9
C1559382192389*48
6623646(3(4411526150A1
JB51910B8561-#00$$6"066212146151142685
154(546212)19131491
91585!5115
6629641164
KL51
9144410:644E491-85
45/2'646864
4(5415)349134238545/216191828915515
4
8154(54(44854
3
M494)410494)4*21-154(54(44854*284491$6585
#00$8512146141N4O495
1/
4851214615/4
O
911515494)4*2
012341562489
482
14115591112
12
90512!"#18$3
448%5
&'(
$)1*+623,+1&311140&6624,5&-5*+&155&6+10
558545.4&
3
44&6/1&14621$64459&4"/6585011
55&'
48+914&&662/96411424234.4%&4141542.
$
&6621&&15
9833)15&593824+!91+-,5144!
91+-/
+4
4&85234+34.4%&15412341562452,5&5
9954141
15%8+5%412341591+46264
15,443
++4123414444+8+&296+6.8+$/1964141&155855345
++&2.
$412341196+$649124%&41&+41+
41414113621&
2319/
+4
542.
$4123412144448215&-5*+-5%*+
4123415621196+$1&1$6%46264,562151936264,51$6%4624375
211!"1$15,'2$982+61+1+4241+112+/441+!"25
196+$$15,011362+4'58234%9134815+113624-&*3
414115.23+858+416236+.23+854419+
58843416&1+$261&
61.%4828640
+4
5512!"91365,'29333
&581858264
5241+1!"$15,'1515,201.84..
32.
$4123412141196+$14
9141&+4.122-&21$5241+1!151914&155.23+85++&
4.1
/!&
+%8%
16
95&44+423!29%25
41+1!91+-/
+4
&48523421$5241+1!54.4+&.
33841234125
14.13985223&91)12542011!16/341445241+1!54
5
55/+151+&8523491)12542011!&
+42%
55
/+151+91%151+&&91+14&6/1+$,%15241+1!+196+$15&
+5
858218553482
&491)12542011!5241+1!515444412341214142
9+1+85233
++5584.4829+4916&13144%
55/+151+
231&13141$151964&8523422311852312/
+21:4!-5
544584.48%
55/+1552862361+
15,4415+34+8+&41234142%151+514141&
+88491+42-&15
5
55/+151+412341214&
+%
16
95&44+429%
112!91+-/
+4
485234
3152,412341214&6231+85548291+-2
85+!29%144!
51.14,261485234+34.4%&1541234142115,441&44+42+&91)
12542011!1519141234+348248+%
55/+151+$*&11
&*+$48&
++85&5842.
$412341196+$1&15&131+1&6&13+
$*&61/58+&44+4584.4885+&31$1412341196+$1&355
28/+151+31196+$1&5915$&61&44+491%151++1&8523
4
&2;$9+4514*54621,"131982
/11+'200<8523&85
%6223*11&/
44852323*164259+4*22312+
988%842
9141&+4.14%-&"&8&418+63141+2/21'(
012341562489
482
101234119610111141
/
4
551!13650
*)
#1/
4
551+2
##313650415205112"154!61482#
"
594!13656210
!8..#"$4444412341214151911444593
)41
$+151913
338
44)
#1/
4
551+2355012
9
4
.5112316"$444412
9
458423#)
#1/
4
551+
12
9
4
3
338
44151913
44)
#1/
4
551+23.85#
91"151501"
51"$4#*)41
$+1519132
5)
#1
/
4
551+151913
338
4415191)5#24112+)4#912+24.)
#1
/
4
551+5
85#2584415191#51231*)
#1/
4
551+15191
,-141.14$5
61
9
382#15!17#51"
62"$14#
$42482#"1515191131!141308
94151!1/
4
551
:;7#41/
4
551
<;#951/
4
551
(
/
4
551
=9"/
4
551
>?#51/
4
551
@&
1/
4
551
A915$1/
4
551
B-
$51/
4
551
C11C5/
4
551
9/
4
551
012341562489
482
91
4
551
491
4
551
0
4
4
551
024
4
551
1
4
551
11125!5
995"9!
3#$4151%1
4
551&'(2231)62*5+
,1365+-23*5+2
9.
4/51)4"#
4
551&251)44411435810
15415191!!13*52358115415191!51)444828!2
1/191113!
!
)8.2)8356%+2
1/*!!1546585")152385.5641
0
3
441#41
&04
2964562238995"625441#$4151%1
0
4
551&0465811541519915"!!
#
4
551&15191344
3.%50
9115198
95!5
995)451"9/2
131152+!64151996
111!5!5
995251)4'5556
-23#$4151%1
0
4
551&1519915/.5412341514+3
5)
594"9!
91112!662
3+49115+3+!6622!11231)1/136264+5)*465851
51%8285.
5!593821214631)152385.15+23191!112384"31514123
!
283"91/!848/44"9/%6511274115624
2#894
4
551&':2
5.,1365+-91418.31581154
151914)44451"2!;"943#$4151%1
4
551&"3
3"15144"
2
3)444851+!14"1%854
3.39148
3
44646!23142
0
11441!4
2#8951
4
551&'<231=,1365+-915811541519151)490
23
"823
#41
&51)424123415191!5
!1510
13626123854."94
!1%48!)8/51231315
!5
15!*5174!)8/5
!4>12
!)!
54822537.
554%14*!58410
1562124123415621!"23
25114#8951
4
551&04238541234154
)!
5482
!62!2
5..9
5
!15%85234828"
41234120
14845844.9/
<3
5"949!
23
)4%1
/1!41!120
14631
/1!49
5
!62)!.!
234828%5)
!
338!23
)4%1)10
444.2884
2#?
4
551&'$2964562,1365+-!
)8.23185574828591
44
5!5
995)444/5131223125811541519140184%591#?
4
551&581154151923
)
51)4"913185574
44646!"
23
3%23*5+2
9.
4853185574
442964562238995>1#?
4
551&2964562238961%3185574%"6223*5+#41
&
2964562238926"!!
#?
4
551&%591581154150
191
5!5
995)
51)4
#$)
4
551&'>,1365+-2174266%15358115415191!51)4821
)15464154+54114+)*+%6
2#@51
4
551&'@51,1365+-)444/51;/62;/3581154
15191!14"9791
44)154641592
012341562489
482
51
4
551
5136521426615152385415121
98215!1"54
3384123412141315191"14#$
51
4
551
2142661592311"144444"982235%6!4&158824#'3
"%5((2123
2&41234156265231146"5"593)*
9
3"
8545"1154+15238582)5*151"14#'34,
4
55152385-
4""
)2&4123415191")3)")9
348265"%5231146"9141-
13)1!41234121414#
.199151*9
/,1/5!
4
5512"-'!2311365
58115415191)411562124123415622
8,2"1!2314"51#'3
4,
4
55123854"1314)011514"136251444828&
5!5-
"5938214)4825641
3828&915!45982412341"%1"*65851!
911156215"6234621
5)182858212146&915!348"6621"1
"11234%59)*5854&!089)5!1982
5!91151415636261&
915!1",2"1!231"155514)#
$2
9
4
5516514511365+!91"()"&9)43341511
4
551&1!")6415515493341511
4
5513581154151-
91"141!98248&2
10144451&)2
9
4
5519)-
15"5
995651451%5852341!151914358115415191)"(3%5#
$0
*4
4
5515411234"6*122613651!
5!91,)3-
92423
5854441234156213&9155!15"
584
34"315"%5(44"6621"
238984#$,
4
5511")"%5(44"6621"1",2"1!62359384"%5-
)4
800358115415191)1"#'36235931))85441512!
238356"
29
#665850
*4
4
5510185544+!&
!
"6444482
"",2"378238356"84"%514
800&!+!&
!,2"
3152
8"6624#$0
*4
4
551+!)2"
)854&
!
/,1/5!
4
55191"(626448
33#918554496+!)2&
!
41
*15190156(22312238541!%44121"
584
33&!+!&
!"%5(-"%5(#'351142661:2115(56!314415852344#
;41841345114261485234"&,
4
5519)1238541!1"64
"
584
3&1551"13121401"
584
382
"43162341
*-
1!%441215"5933#
$21,
)
4
5512(3462136541512115469
2385-
4&9)431)),
4
5514*2
"#$;0066
<!=11123"(3315
1165!1341414>100(6238545"%5(44"6621"(34621&93
"
152385821!4123412146231"64$;0066
<!=111")"%5(44
4
"9146261238521,
)
4
551-4#
=9*51-9)4641513
$
!343152*658"1214601981954144%"&29*51)415-
191"23111"2389815"%5(44"6621"1411858"#$35800)"
!"002385429*514*2
"4
#?0621@124
#;00621@124
012341562489
482
1111124 !"#$
%&1124
'&()#1124
*& 1124
+44
+452,16221$
-&.+41124
/!(1124
!84,40,
1& 141+19223123111241,15621241234156261
,23+85,404854
34
241234121412262354,1461271+4829951:4592
2
715,23+858285)8591++14592+1
+6;12121371<13148=00
112429951:15199157
552
326235141211+
#
+7>5191+4"2
+78021519
8#
+7 >5191+4:"12 ?
+7802 )18555482
2$ 715,23+858285
51,14626@+2+1552829951:1519116232
8854
34
22
+7802
18555482
2452593+5
852+8=001124:121461++612@5A+"
A368#
+7>5191+4:,23+85,40B
8=00=1;1 +1:=00C1< 1+1;321$
D8=004,
34
+ +1:=00=415125462 1+1;321$
8=00#
#11!14155
338!#
2000
#11!161248!
3!#+4!62353
!45
!2884#2%
918%48
58626,5#2,4#14/!!191"151551!%6585%
12,4##!9#2!
338!1!1519#!1!112584
4*
3%
000
#11!1
3384*
41
15191362431451!,51001124151913#2
111133,%
000
#11!1151913%9#!1!23853431%43422,4#4"
6,51!#
2:1141625++#13#*#+!(482"
1,5!#13
584
382
2001124;1"54215196!1591291)!#3924!64
#
964116461#!191
23482811#001124-95115
1914344426621
#96411#769#!4
4
)
5%
24%
4%
462!91<5181151!+1855(44*%6291
2344*2951
1519143444
22214#
!21551!535
#8+8523
51559382#5589
2!%8523%9#4
44%
66!4151!22214#
!7=55(482823!854859*!!(5#66211
96!6!1151226641551!5#3!#/38545"1523!85*!19)2231
18523612266+1!%191+(34*288+!#2+#34
25114!122
214#
!1519-951581!15415196!4
34*56417)26%9#!4
001124-9518/22214#
!855(482
444593%915114
91155#3285!!
65855641
34!122214#
!4%915+1!43(4,%
2311455
#223
448523!44593!#1551#2
5)23*4/3148!%3
!
00112415198523%91513
3384322214#
!4%!19
4459331#2
5)23*4%
2214#
!"#51#+,31!1414!
/3464114,91%
32
9+44#!4+1(234114
91151!5,1223419135+10
!4#!2
)#*!#85234%
012341562489
482
85234459811219155415123
2281412
485234!
1415123
228211226"15464151#
!4815623$4144%1&'2214
15191423%26%961&'2(
214
)12!54252411151912112622141518523
911(
51$462613#'3'2214
)12!54252411151914*00+)1,!124-9(
51151923%5.41
!2
9
48
3155
338#'3'2214
)12!54252411151921995&1
"!84196&15#'3
4441
!15191344
391'2214
1519911196&64911(
51$4#*31551.3622112662"
8284113121413/)0(
43
2$4231114151$491#255113.12141%311415191
"
823
2$4544915&1829429145854#
32231"
554184)12
21'2214
151923854
&
913285!1&8523/)0(4&413214
&44593(11&15.1
91
449484#0641311&6'2214
4$!2
24
#5!4
'2214
6.449755$48242551.3
&85231&
91
44.449
15%56133191#
8#-31'2214
614755$4824'85239614641551.38462
122312
5$41&91
44646159:;:<:;9:<9#
=#>0'2214
>0755$4824?34
2$4
&85231&15&121
"
983
44>051&1#@191551.3
&5
!9140&151"(
4
505&1&62694$!2
66&122661291"1515(1#
A#>0-19'2214
>02691551.36242&>026958
1551.33>0(4#
231'2214
15191)12
21'2214
1519132
59
"!85462
33841&41234121413#
44
B&211
*00+)1,!12415191623$46211&.!48"82348854#'C1(
418545&D4
44*00++
B&-111231321$426615&
9
11(
414%1&1623.4161&2664621623.662158*00+
)1,!12415191141185444!!4
94!2#'
B&15"
91
6624941623.%5C14194
B&(11234%53
4C1(
41*00+)1,!1241519965$4#*412341214662115623%541
62.9"!4444!621
4
8%5662114652311"156#
25.231
338155!*00++
B&-11151914E
?115(
1913#C
16
954442!E
?1
86285223!
3'9@
(012425191426%51*00++
B&-1(
191%
4
4#'
B&
"!8261&.18F(
#885844#
11&133%
&E
?115195441&)1
G
4
551
21"85915&014G
4
5511519641855$4*00+
012341562489
482
1165
6621484
23111131!1"
#
$
4
551151954485584%4&81
#
'0
9"462(1413
6146235641591362
2314)*)*2
4
4%2385+8
,4-3
.51611
(141
231161
423898484155855/411#2318545
19%23854
42389
044124
."5#16244124
1"5#123-19132311
5821+13621#%4&919151551231#134!5119151
23898'00!161241519114118544+783-6232415+12
5984%5#'00
15191"23
6621145/4+'00
!161241519969151551231#15915"5#19486219
551231#131"5#1948
'31855/4
44
2311444
93444#/4%4+15
15(1414855/4
4431
2311649#181323111,5#-44
662(141
23116%5#11234,513114662114(1
4115
+'00!161241519965/4+214629
71"%1519
5815144!1"
#$
4
551151958%15131513131519148
1231:184%;3%4&41234121458
15
234
4441%156212412341562
0(1411#15131
545+#
285%
%85&34
15
234
44
(14165#8
4612
#85828915+&5
%2;5
33?A11225841%1562124123415621
5813
5#54
9151419442338/482
#544B
C11
94<31148
528>?D6315+,15%
7#1241,51
23114641%15621241234144441(823111A1%6338
95196463115
#1314123411#9664915%85&3462
"2
912346242231114+8423%4
5943E%"2
15223-19
4114123415621"651331312143151%14
2612%
4123415/842311%1335-3151223111
012341562489
482
415142141231146234813423114238541234
48
5156362613
!
8"891#$1514
$1$1415124%""14123!
1148$4
!
8"&'$1415124%""141231146128$4
%1413("15662(556621"1944
$85544"162#4!
44441234114141231142385&
01514224))141)234"*+,491#1515(1412311
61
)18$48414165)8$12146"1)4215231!
1#
5$94
4141"%$488"45854,9141!211"4$
9141!2112155234#4448285-
18+,21)2314(5#(1.
/)
025446911511/)
02+
4#)9124$2!
"3114'""131214"1304%$1314854
3,
3)
338&
56748'59"
:512612311234621$2291141"%$488"
45854,9141
1412#854
;19
417
24245)
28
41$911$362"(562854
3422
91*$
$1223(15158523451$11#152
51412311
61'351141$#15
5)4,<=>6$?32389
@?)421514151249141"4$91412155234#444828!
5
A=$22911$41234121414$623421$*4
1B291"164*5114(2615191&1B19
41>442621B19
41
>4
2'31155114(2611519
417
24245)
2885#152
54
231119)1$15185544,$15)44,
C'3148$*$23854141#152385,#155146494
8""
0123411)96$16415913621
>
)4
411851$)
5
64159133
41$982311)96$1
15193626164514(9,)&
01512496$+65
4D3621623
4123415621
285834,28
58491855482
E65
4D3621624123415621
012341562489
482
155938262346261152146
91523
4151249665
4433!"3165
4459348#1413
9148#591564$
!%13845
2#8
38291662415125&
'!%151
223#8
382&
(!%1
)12662)48#14131&
*98123121542
565
491+
593)19185,
5-44)
41234154.155938291+1515,11311!%3/0,
14111-
429/3-112)542524112#8591+15151165,
!
06415133+15#1413234)84$11231.1
554
)12+15238541554)1315
5
)12341514
+152385194941982
-116451116624!
%1+152385845'45131982
-11155-
#8523462
(982
-1969852#8
3829615+
4!0234)8+
5,
44826446415133+15
411562124123415624#6134355938,
2
+1465
91+
593
4446)9
63#1!
028583428
58491855-482
764151249665
1961121623114519
4#854613
9148
334-
4
4
5.15593822231
95!851
59%141521315
234
4441234154)5
28!:
4
2911,
13
2412234123414;1551562341
#5#58
234)841-131485!7194;523
2-658)51
5+
98
5555+15238591
5131982
-11
)12662114
5
.15593829182
9#1551234)8194;5
+
15+
)5#5#58!<
523
24))-658)5
455+15238511515662114=91662344(
982
-12314415>
.1559382#8523
?2383568
84
3!
<4122341234121463/014111-
42
5238548
88883
5828
362185544
4
#8151936265859,
115141384-533
!
0
#81519362
09%141419623141216-12415124964
4159141
982559382
1519131223
4!*8151512=32,
914>2-18529%141,1341#13144415124961519312333,
4)46-231-
9
;94%
2
+4"6156-1219,
-
4859%141446291+65123
2151462462+
4
62341155!05-64159136219%1419@%A9/B
99
<1-41C5)12=B<C>+
984)9154)914134
4!"3
012341562489
482
9141
14128591412121211
44
9445
289526461854
34482858554!4"1#9141
141285
$%1414151462&4885&484585!4"
%411'41512496412341562148
#131441512496412341156362148(!)15593824
522*45854(31961291"315!2385"
4&91615(264624613!14+(!
91
5
56984(522*
4,'6231*"515623462615(4&!1!
3388285(62
4
8-141+.
/
4
2(!
13
2423
84(964355938251522*(62
!
91458523,11234914231414031&22314144154(91
5&319,&62461591231923484
(9)15
59382151234'616236'5
-6!8"482(91512142661513
24!441512496
569
82841
/15+1231
98"4(*94231123462919"
15!23858284554464
7(6
244762692447123&3&(8
)2
544602%1762631%
751!14121426+1
9#34832!
32
5""154
5
48415124
9623,11234914231464:23853483284"85
45*4
44
234123&3&14#63;<7=)));2
9>!441??
)));2
9@A154
82"*123&31165
B:
5114151249641+5141914585828)15
59382"84(9341514(!
5"5'4+5
593824(9151562&343
2154
1563626!1323+
2612'9126140342
542482
9884&46
!14(91519,151411563626!1323+2612'45"338#
113141584!44(!
!
!4!
3385"3"42482
4
)1559382!
3
C:2385
56234'123&3&14)1559382151936261(
41!156254491944
3"21516229115146261
1562346261(6231129
5
!82
8883
5828
#!82
1
59(91591944(!
915
12319
59159829
54!-6!86231,)15
59382
546234'123&3(15164111211591142(
6$3
17=)))D124
9?
1?A(36E4931F47=)))
5
9?
49314?A6236052171126012431
910
52354
97=)))1521
?44?A123&31
031123&3&!23854865(!
91!48
33151355938
2415124966123,11234914231464:12319164144+(9
012341562489
482
5
482311234914231414
15131421852
55
3
3
5
2231
5582
415124964123415621
4
2115
5441!6126
9155144
285834"!841143559382#421414$4624
31231156462645514%162911%24624114
8&&
$4621152
54&'&&111314&1$!1413%469$$14
41414484(
)*1115%4415155$41942#96625641155
3#14123412141441234121414!84415124961
911515%1+91
#12152385"489
4
4415!84!8523%
15!848411234%61226,6234215
412341214144593155239#585!84152385"4-
3"44115624915158!143559382462412341562
$131464
.285834"28+12313
61226191551591$!11144
41156241315415124966291&34"282$162655,4$&&
4613%4%50
94123112146&1514613%231!1-
!123
4!1
#8"624151462414/8
01*14114
1441512#
5482/54
82"/4123415%-
125$&$3%1*141411562124123415621323854"41154
&19#4482
34151249641234156261&1113621#484123411961
214111511141512496
84'3496315%44155
9141915%44&8951!854
34482448!6141512496
$!156261658&"5
Szoftver tesztelés
9 Hibakövető rendszerek
Egy szoftver készítése során és átadása után is merülhetek fel problémák a működéssel
kapcsolatban. A szoftver készítése során és gyakran az átadás után is tesztelők keresnek
hibákat, illetve az átadás után a felhasználók futhatnak be egy-egy hibába. Ezeket a hibákat
javítani kell, amihez a programozóknak értesülniük kell a hibákról. A hiba felfedezője és a
fejlesztők között a hibakövető (bug tracking) rendszerek teremtik meg a kapcsolatot. A
hibakövető rendszereket néha hívják hibabejelentő rendszereknek is. Hibakövető rendszer
például:
a JIRA,
a BugTracker.NET,
a Mantis,
és a Bugzilla is.
Ebben a jegyzetben a Bugzilla és a Mantis rendszert mutatjuk be.
9.1 Bugzilla
A hibakövető rendszerek legfontosabb tulajdonsága, hogy milyen életútja lehet a hibának a
rendszeren belül. Ezt a hibakövető rendszer állapot gépe írja le. Az alábbi ábrán a Bugzilla
állapot gépét láthatjuk:
9-1
Szoftver tesztelés
9-2
Szoftver tesztelés
9.2 Mantis
Ebben a fejezetben a Mantis (magyarul imádkozó sáska) ingyenes hibakövetést támogató
rendszert mutatjuk be. Az alábbi ábra a Mantis állapot gépét szemlélteti. Itt láthatjuk, hogy
az egyes állapotokból, hogyan jut át a másikba a hiba.
9-3
Szoftver tesztelés
Tekintsük át, hogyan halad a folyamat egy hiba bejelentésétől annak lezárásáig. Először is a
rendszerhez hozzáféréssel kell rendelkeznie a bejelentőnek. Viszonylag egyszerű, ha belső
tesztelésről van szó, mert ott többnyire adott a jogosultság a hibabejelentésre. Származhat a
bejelentés a megrendelőtől is, aki kapott tesztelésre egy korai verziót, vagy ami rosszabb,
már rendelkezik egy kész, kiadott verzióval. Elképzelhető olyan bejelentés is, amikor mi
vesszük fel a rendszerbe a hibát, az ügyfél telefonos elmondása, vagy levele alapján. A hiba
9-4
Szoftver tesztelés
9-5
Szoftver tesztelés
9-6
Szoftver tesztelés
A hiba bejelentője ezután megnézheti, hogy hol tart a javítás. Láthatja, hogy a hiba az Új
állapotból, milyen állapotba került át. Ha már kiosztva állapotú, akkor jogaitól függően
láthatja azt is, hogy kihez került a hiba, és milyen megjegyzéseket fűztek eddig hozzá.
9-7
Szoftver tesztelés
A fenti módszerrel természetesen nem csak bejelentett hibákat lehet nyomon követni,
hanem akár új igények megvalósítását, vagy akár egész termékek gyártását is követhetjük
vele, ezért hívják ezeket a rendszereket munkakövető (issue tracking) rendszereknek is.
Utóbb minden menedzser álmát is ki lehet nyerni a rendszerből, azaz mindenféle
grafikonokat és kimutatásokat. Ezen kinyerhető adatok között találhatunk fontosakat is, mint
például, hogy mennyit dolgoztunk egy munkán. Ez segít a továbbiakban megbecsülni, hogy
bizonyos típusú munkákat menyi idő alatt lehet elvégezni.
9-8
Szoftver tesztelés
Tartalomjegyzék
9-9
012345674681469
8
B?-(>
"##C,
>
8D(
01.E?
8F!>1!
3
!!+
12342567
89
0
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
8
0
0
9999999999999999999999999999999999999999999999999999999999999999999999999
8
0
999999999999999999999999999999999999999999999999999999999999999999999999999
!
99999999999999999999999999999999999999999999999999999999999999999999999999
"00#$%
!
999999999999999999999999999999999999999999999999999999999999999999999999
"#0&
'(
0)
99999999999999999999999999999999999999999999999999999999999999999999999999
*
0
+!&,
!-$
'#$%
0)
9999999999999999999999999999999999
.
0
#
#(
%
!
999999999999999999999999999999999999999999999999999999999999999999999999
/
0!
!
'#
99999999999999999999999999999999999999999999999999999999999999999999999999999999
88
1
!
!
(0
999999999999999999999999999999999999999999999999999999999999999999999999999999
82
"!0
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
83
0
0
##
!
9999999999999999999999999999999999999999999999999999999999999999
8
45$0
'#$%
+
$
9999999999999999999999999999999999999999999999999999999999999
8
6!
#$#
99999999999999999999999999999999999999999999999999999999999999999999999999999
8*
7
4
0#
#$#
99999999999999999999999999999999999999999999999999999999999999999999999999
8.
8#
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
89
:#
!%
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
8;
000
23567589
5
0
!"#$01$%%&'(%)%&%*&+
,-(.$*0/011&.23&.*$4
5678&88."8/01)09
01
1245657589
8
7857855
8
78578568
!"!#$%&"!'!(!%!!"&'&"'%)'*&+,!
!"!!#"!#-&#!"!"!./'&.#'.!./0.!"!#!#"1!2"
&'*"#31&'%!!"4(!''!(&&,&'.'!"!'#!0!''-
"&'&##!!'2!"!!#56789:+!';./!'#36789
,!0'1&$0"2#%4&'*�(<,!'!!#!-!"!
1"'#$,!#!2!'2"/$#!&=>+!'1"'*#3#'!"'#'(&#(?
@%!!"4
@4!"''.
@'/&&!)""4
@"!.!'!(!#0,0"/!=0!
@(!2"<#!!'0+;..!#!"0.
@1&+00(."<,0!'(!
@ ).'(0(#'#=
@(<,!'!!'!(!#3!'>�+;..,0"/!#&>!#)(#0"$0"2&'0
,0.!1>
@#)&#(!''!#=,'/&#(&.
@10#&"/#!!'0(&.*,0.!1>*(&&'#'(
@#&"#) !"1&+00!#"#&"',0.!1>
8"'1*3!"!!#$(&)'+&.''"#(.)#31!"'("#
&'*+)"4#*#3!2+& (!"!!'2+)"#4*#0%&.(#*,0.!1>*
+)"#4*#!./!./0.!"-A(&#&#!!'00$!!!
+!'"#!#"!"3(!'/((!.(!&+,!!!!'0(!41"()&#
"!.'0%;'-
!!'0!&""'!.')./"&'/"+&"&'0%0&+,! !"!!#
+!>'!0!&"3("'#'(&##*>"#!!'0!31!">!'!"
'#'(&#"+&(4*+& -A!"+;..20.(&(<#$0#1
!.0'#'(-8,!'+!>'!0&"'#'(#*0(0%;'3
!00((*&=#$'0.!"./.!"!'"./&00#<3("#*>,="#
#$'0.!-A./0BBCD!E 4'!+!'(00!"'#$'0.,&"'="#!./!
1=%)&#?
11,!!'=,#$'0.!?0FG0!'=,./#&.?HG
1"(<#$2E9!'=,#$'0.!?0FG0!'=,./#&.?FG
1"(<#$26789!'=,#$'0.!?0CG0!'=,./#&.?FG
10(!'=,#$'0.!?IFG0!'=,./#&.?0FG
1"(<#$2'#'(%&.(!'=,#$'0.!?0FG0!'=,./#&.?JKG
'#'(!(%&">*''%,!2+&"&.L!131&./&'/",'*)'>&"
(!.3(!'/1!'/!!"010#&"/"(<#$#3'!1!2,0!0().'(0
&".&(*&=-!!'0$!!0.0>*'>!''!(0"/31&./
0
0123456789
3863
8
7
986352621234567882534
8783
7685
7225
2
2
26589
18378062
2
26589
278
2!89
23425
2
26
21234567882
062123456783863
8
5333
8262
2
26589
3863
837873
378
2327
0 377
262123456789
923
9658542344
3863
2358527886
8
3062123456783863
8
782
23
3
"12
3#
319496$4
2!
49%&253
5386"19496$!
249%&
6
'3804
2!
9
292386383
17
23
85
29333863333421239
83
3
72386371
388830!
249%
6
'38426212345678
94
39
"15378
8269
"1523"12
23863
*7
9268
8
3863
8
38
78445
2933
319
9672944268
9
13344
8623863
878)6"1867869326894
39
"19
582
8
18
2
29878337
7
062123456783863
8587
6
'38"12262123
6
877
9
12
5"
91
2765
223863
89
223532626
9268
7379
3
8
83
766
3863418673869327
)"186
9
!
8!77
83863
8786
6
8"186329
2
2
2623"
88'38
"2
2944
13383
062123456789
5
262
54473863
873
3
'33
#
012345678823863$+!2 082
68
!
2
71'3792
383& 8542717
3795!7"
42(
8268
3
26998'323"
(
08236889574539
962
72212
82123
22123
3344
3
68478
2865
2
0825
3965853
3869
583863
79
3
(
7
3
9
2
2
723
96589
262
2
26589
42
,
!792
735873863$,23 0
!792
73583863
889422621234567842
383& 359
3
5589
2
3'
78
1833863
7
)
895
767
92716
37
!7"96
367
(2
3'
82'933
91
9
2
813215
(89
962
(
3633
23589
230
!792
73587
3863!276825
6
44229598
9296587
3863
87"18632596786
73378
"18
3
3863
7
012373735873863$-373 0621239
737358738634
767
9
383& 2219337373587
33
(26
6
3791
42193386245
9
2
86
86245
9
2
"428
(0123456788673
267373587
6323962
2./*0/01)0
33
261723
9658786245
9
22342566
52-75)889)81
38
2
2732:),0564
9!7"
;1
73863$+!73383& 01
738638957685
7
926
821239
962
"96658
(266
37
86245
9
2
826212345678421775
31
7
1
(
0123456789
3863
8
873863921383 03
873863895
68
9
262123456783633273
3523
8373!12"
23
8923
96#
5589
23$03
87
38638952%219332123%7843&
383
%383
67
7
3%67
2%21933865%
9
!8
8'
19
9658226
535
286714
'!3"$
(23
98573863)!983 03
83%3863
225
28671
68
383 2'939824482
9744
168
83$
*7
2
1687 23
985 23582 2
%+
39,37%2
765
58&886333212345678%#1983589
23
7
3$
03863
839544798635
965872
32352237,7
!8212345678'
863878
242323587%+
3
6
&313
8
8673789,9398358$06212345687
343&4486&78
'91!
2399
25
396589
&3
6
4%
26
2123456784#
73863
837
7$0'93982443
889,939
-
.7'9%57#
%3863
8 067
2
97443863
87'
2123267'9%57#
%
473
67
32
367'9%57#
%
531686
2,89
#17
$*7
26212345678
98862447186#
#212383!
353
32865
232
895266
37%91
22
#86+8
%5
3967
$
05
39658
3377
%
837
3
7334$
,3
873863 08%54222'!
792
73587
783542
%
767
9269
%'
"
23
486,
589
2
&3
%
$
03
,3873863
88953863
%
7,#45
582$
.'767
27
%3863
8 06212345678'
86389,37%2
765
587273
32
72
2
73587'567827422
97
273%5
3967
1
2
2332''767
273
72
2
3582$0'767
2734
2%5
39693386
63%5
3969333
83%3'9
%!323763863
226
533
83%%!323#
68$
12262123456789
3863
8'9398'
2123%78
84313
22
9
2342
73
5442'91!
%73229%598,92%3863
8$/
865%989
22%
&6
7%
3
262
544736
-
2756#862
%2778%3
23863
88
2,89
234226212345678
6
862
%4
0123456789
3863
8
2944
389623
8443592386
65
1
68
07878693
863872
86
252
966223863
886
!333582
GHGH$,+I%$J$K$"##$%&%'($012&1/-*3/$&3'3/1.
L.//-.I,MN($%)%*=;)1&&1-3/
0788675@4886783863
864926212345678821983582!35
6188>
2
92
954422
83933!
?7
395442788
4
0123456789
3863
8
1
047639858789735
3
86382
2
963863
3
715
3965835
33288
35323863
832
19
2198!35886
5
7
"6
6
!387
2
58
78
26
3863
929658#$%&
3837831
93'
!2923863
86!38
26
8
82
863847
(782117
198!327291
2!2
2)89
13863
32
0$%&2
2(
863844
87*
+71
3863
5
!35822
!53
)796
,238633323582-287
853
3372
3
6
)728!7886226+92-
287
.
39544
82/932
/291
198!3582
7844
6
33
4
0238633323582-287
853
3372
3
6
)728!7886226+92-
287
.
7886282/932
06$%&
6
!38
9236944253919
22)
9
23
44
3512
267
35
396589
6388706
86!3333863
9442
9
2
765
12
194
2
632
2982442
682317
$8638
5292944
21239
9
3723863
!582
823582$95447
3
733267892$%&
6
!3842
863
22244
6523226891
9
8638378622244
278862
68326
633
278
23456789:;3<=>8?65<@>A<B>C
09
962398212345678
8638895
91
23921933198!35829
87
3
4769
"
212345678
19
#359
3
55837'
212345678223
03721239
329584
8613
886*
212345678322123354
5
3232
2
.
8
97 5)785
959
3232
2
072)9
36
579
1589
73
15
26EFGH18626H2)
I&JKE1
606EFGH1863
8LMNEOM
142!367
31862
26H2)
864
.
.
21234567842359
2
2
7
321234567885742
4
3
6(5
396589
23067
3
838638333179
15882
26
7333
!
589
5852
8
738
06H2)
8343443)23322123
637354
21
68&J02358
428221239
79
285852P59398244
82
!354
2*
Q&J0R$0JM"E*212345678354
5
212327
Q&J0RGHMSKPE*2123354
26
!582
Q&J0R$0JRLITFE*94
399
!582
Q&J0RSE"IE*
2865
212327
0123456789
3863
8
008693589
582
0 !86"
##
212327
0$!%!359
3
&5589
212327
0%!359
3
&5589
'1&27
0()373221235
95)*9
3232
5)2
7)*83#44'178
7)5
967
! !+,-..3232
9
#6/3
)
168
$0,-(958141
142!0!3!$ 0!4354
2%5
168354
2
53589
582
37
#3823232
9'1983585696!0!55!0,!%$0!354
2
,!078.....0373#684)
6386"
33)723232
9
79
/2858538
589
5853/69:3283589
23..
-$81"92(:33235822221933354
5
2
06*821234567894&
3:9
82
582
96286)987)(9517'2
2"189
'1'&
)38
2*25623.!6662621
;4)2
<=>>?@AB=@BCDEFGHIJBKLBMNOPFQRBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBB
S "22)186286)5
623'.0()37"22)18838/
2&
)3832*256'86#/3
21623:)
285696.021933
582
L?T?<AB<=>>?@ALBBUV=>BBWL?VXAYZX<=>>?@ALB[\?V?B]]]R
L?T?<AB<=>>?@ALBBUV=>BBWL?VX<=TX<=>>?@ALB[\?V?B]]]R
BBBBBBBBBBBBBBBBBBBBBBBBBB
"22)189
2
16639
.
^_`abcdefghijikidlkmgjnok`kpqorsdsaskgbedaiftacf`
062*95)*988693((&
8638666289)
'2)262123458789
834)783#44(56784'
5
2(&
8638uv*7)33/68u
'19
58u3863
884/638.!6)(56789
39
7)*
3&
)3)
2621234567882
864)u6786)"
15:
2
'19
58862
286542)
9(91:
623)2
6745
w26742)
x
'19
587)73
2&
)8yu211724/638)
5)862421)26745
233232
26)722)186)
.0z
#19)186)
283247
7358
2
(9)4398244u2(&
8639)186)
"172:2
2885.!6)
39
#/3
)*
82&53212345678
#)*63347639832)7.067
*)*177)*
3
7
39212345678
"
15)*9
23)/67
699
96'
)2
w82)149{y.06212345678(&
8638)
262
5447
699
96'"
15)*9
23869
58
x
#)4#633)7
(&
86397
#)*63w1/
9")382)149{y
"9&
37)3517'8
#)*63w"9&137)32379)82)149{y
1983517'8
#)*63w1982)149{y
4/63873863
#)*63w";"91:1379)38382)149{y
x67u
8
#)*63w"91:1379)y
0123456789
3863
8
!!"#$!%!"!&"
06'(8)
15*(9
3+,965823-+3*,3.2*/5
782*0'(17120)2+2*389
2 7800
-43
65
4*4./3236/
26212345678.589
58)2+2*438273267+23
1289)
1565*
2
,3=
1+I3*7@
8
33*2.=+9.4J1232428K
8
33*2.=+9.4J1232=7
K
E?L67*7372
76537M85
9.5*(
86I38?N,,626OPOQR?7D05
9.5*(3
53.589
*78H6
*4321*7?07*7372
76537M85
9.5*(42*262
5447)2+2.3+
3
2
3/2
765
*7@
14C*2.
39*3+9
C=7
8
2/173C=7
C183
423
'+9/*1C1/.)C183
9'C2+3,74C183
39+C1/.)C183
/8+C1/.)C183
S?T6+
55
9.5*(9
3+,96232
2?,,62=9++5839*3+9
=7
32+32
.23
53.589
*7?
N,,6262
54479UV)2+2*3893
721*7@
2
3+1232428423
/)39*3+9
=7
393+23K
N63
-435*26H646+
55
9.5*(3
55
I3M9UV)2+2*389+3
3+,96*7?0
)2+2*3889+86+
63@
WXYZX[\]^_`_[^X
aZbYXb]a_^XZ_cdecb]WbX]fYXYgYWb]hiiih]ZbWbXc_jW]^_YZakelbc_j
]]]]`Ymc_jdecbW]ii
]]]]`Ymc_j`b`gbZW]ii
]]]]`YmfYXYdecbW]ii
]]]]`Yme^WXY^abW]ii
]]]]`Ymc_jkeWX_Zn]ii
c_jdecb
]]jZ_[\]o]p
]]]]qrsturvwwrxyvzv{vriiiry|zx}~tovx~q
]]]]qrstrvwwrxyvzv{vriiiry|zx}~tox~q
]]]]qrstrvwwrxyvzv{vriiiry|zx}~to
x~q
]]]Web]tt
]]jZ_[\]]p
0123456789
3863
8
!"#!$%%!&'$($)$!***!+,+)-./(01
!"2!$%%!&'$($)$!***!'0+/(01
!"3!$%%!&'$($)$!***!)-.%/(01
!"/!$%%!&'$($)$!***!"+-'(/(01
!"4!$%%!&'$($)$!***!"+-'*/(01 5
663
7839:
;<3323=23>?@0A
:326
944
86B333C2D2:E889DF
GF0H983
3D=9658D2
9
586B333C
15:I
8B3=39J
7:1B3=23>F08K
K8B38C2D2:E827L
2
3D1232428DE98D1232428<:37
E2:E
<87:K42E
<CE9:3D9
;7
M
2
3D1232428DE98DE2:E
M
2
3D12324289C:D83
9K8M
06KI8
7D:I63
49
28H5
H589
58582
H2N126
86O
38D67>35387::72H587
7D:I634F03
N82123456788H253H589
58D2?@PQA4CB3338K1CD9KD2H9
5
:2
D:1
68DF06RDE2
834:266STRUVWXPTRUVD<37:9
23
=32
2
H26:76:
E
D2FP7:1
3C2D2:E8:5
KI
O
7:C2D2:E85
9H5:42869
587886;9K
2
:72C2D2:E8
C2D2H3D
3F0H:388437
383744
O
7:4769O6HH>142:;<3=23
L
Y3
N821234567853873
Y
7N
7
3;
=286:5
>212327382KIKI4H>19:
7N
7
394N
3<H9
23D7:3E82
2HZ8
3
Y7:3KD73587
H
53787=39
82KI
7=2KI=23>
2
2
168
834
--90:0.2-AA-B/CD-6786-5E0/0-AA-F-----------------------
-------------------
0(198*3587)22,88345
9
53969332289
(850!"#$G2
721933
HIJ)22,8,82
2
92267333
2[89
23794Y
39
92Y39335
396589
31953638
2
9588294Y
3274265
32
23d44
3
d
38Y
7
22Y3585
H1
29443
83!
2Y
8638
06212345678ZY23685
32
59883425429
2
23Y2269422
95447
82
19835853782
9
386
8H2
71
H92
954473687
6
85
Y22
3H
9
[72286
86
3236!745Y2H1
32
d3
5
39658272337878gY236883
dd89112
6
72
95447
[7
6d
0123456789
3863
8
21239
3
68737358786245
9
3863
8
998
385
68
23
9857
3
68
82198358226
6331983589
23!
86"67
3186
2358
4
67786
#91
2394769
87
8
2198358
878862
372
954475
2$939
96%95447#93985
32
598
3
92
5
396589
23
3
7
78448
4238
786229443"
#
21239
5
2944268
27456582
78
3863
826&23682
233
#95821239
53
826&82
4&21239
2286'
80621239
344
#9584
86526232
3
8652632393321239
25
359
321239
4
86535882
5
2
(
3
3
'
8#9584
533321239
0621239
4$383
38837
243
391
9
)7
43
391
2*7!989#3(32379
+7!
9$98
392123#9589
4
533321239
237888631735
7
'
8
6
$929
1983582082
198358272331983582
869
232
2
'
82
2
26589
7806&#
!7
72335
3962
262123456789
987
'
32
95447#
!7
23767853726&2123456788542
0886783863
78'332
932
86
322781727
82
5
3967
675
358087
83863#3233589
35
399
96
4
53772621234567832
$91
!785
3962342062123456789
75
5852344&378
5
967
9
21983583344
$8
863'
!
86"777068
$8
!
29
7
2224486'
2683
8
9#
7
389
23871422944
$3
"
198358
33#
9
1
26
391589
23062123
3
8
927233262
5447
$8
3!
86"2327
+1354
2
396232
22613721239
68
CCCCDEFGHFCHGIJFCKLMLNCOPPPQR
0621239
53
8281354
542
CCCCSTUEFEHCSTHVCKLMLNCUFJFDHCWCXEVYCPPPR
06733382
3
8828673"
86380694
33$853
#'
'
4682532
2
3589
2
386'
8)354
23
8
9$
15
892
7
262
5447
3
0123456789
3863
8
2323
633
912!9"23
96#$7!23
96587%
&38
6"94
3'9
237"1#198(32"7!2%)3&&
"7
*7
+332$7!23
9693394
3'93
#198(32"5"
,
-067"33394
3'3&
8,0694
3'3&
88"23&
8%)883
4"3&44
.84"!2
#8'
$23%,062/
"186834".
15'
%)6+3&
8
9
$3+8%!2"
9%7273&
880767
273&
8,0
9%7
273&
8834"212/82
$286"5
239"
(!3
$
)6726+3*24!
3.22"/82
55556789:586;795<=>?=5@985ABA@9C5DEFGH
00767
7273&
8834"3")
%8"%864"7
2
7
&
36+*2671!9"23
96#IJ
.22"/82/
834"K
55556789:586;795<=>?=5C:LM5NL7AOB5DEFGH
-0#198(3583863
8,0$7!23
96#85#198(3933
P* *
QR1S*TU,,V4
&18"
"+68,
WXYZ[\]^_^\Ỳ^_ab^c^_^
0824+!(38
978863
8%!2"2$7!23
96#94
3'9
892!3
*$786"
+091'
$23*$9%)2$7!23
96#94
3'"$286"5
2
726+867"3403%%3
"8%2132
$3+8%
3,(%.
15'
%)
5555@979N85DdeDfegg5h:LO5gg
2
2
i
1681")"!5
3967
*$2i6+321'"
285$96*2117%2
5555@979N85j5h:LO5gg
2
2
42"
7219334!
3"
4+!3
2!78862219336+
&*3$530
863
"72""2
09%215852,
)"
926i6+"!
9"0
7
3'842
3
$32
7"8.9%29
42"$286"5
3
!5
396#"!
,6"33
&68
3
"+76"7,
k2865(39336+
3$96'"
428542*2
92""2
%!2
#8(35823&44
$3+8%78
("5
967
K
-%)812"186
&6!3
"3
78359%235
2865(39336+21233(.'8,06
IJ!834"262
5447#19"$96$23#
3865263239336+K
55lmE=<E5<=>?E5nmo>=5p=5qr<EsEme5>5qr<EsEme5l5=t5=5u5>vH
55qrtEm<5qr<o5nmo>=5w=?xEt5pdeyvH
55tE?El<5j5zmoD5nmo>=H5
07"3542"2R6+
86865(39336+*7332621233(.'8$
)"286526323587.22"/8
86.
2354
2107"(/7#42",01239
0
!73
9"
$36"6+
"
3
321"7*
1
168
993386.
26+3
,
-k2212"359%2322865(39336+3
&6!3
"3
*2
92
/$2"76'82
2
26$23#*
)"
926+37"3"95
6+3$966'
38237%%3
0123456789
3863
8
2354
2
376
3
037
212329234476!"198#
58283$
788%382
7
3865%39336!3232
53
&'()*+,-.)/0.)1
0621234567842$359
321239
1
$
476398%358278267
2
223!212345678
21239
6323967
06
537"8212345678
6!
7
6!945222$389
2
2
542$
2222232$1"222$38937
2645$
3
8222$38
86
33
3232
268867$4$344222$387832$
!4586
59
23
9
9623672337$9$398926
1338629$3982$
$26
532
2
$2
72$
!26
$!682
9
539
96"222$389
3$
23582663
286
3%2#83$67
458$3379$352158$2
06458$3379$834$2
7$89
12
9$4733452
2
9
2$222$38
378
3232
26
$
%5$3235882
5$2
66397
92
286$5
"3"
229333
93
26
532
2
3"
986
39
96"222$38932222$38
86
337825429
2
:
12
$3$
86$7
5$323"$186329
2
286$5
"3"
166
2
8335#$3662;<83232
262$6!30
6!447333
345222$38842$21#
537$3
#
383
3=
>>>?@A@BCD>E>FGHIHJK>L>MNOP>QRASRTRT>UVHNH>BRW>E>XF>
>>>Y>@BRWZQR[Q>YFX>>F\
722
286$5
"26
53$95
269$98%3"$
33
>>>]@]@X>>^A>>>X@XEX@X
3
37867
2
926
133222$38892
>>>GHIHJK>L>MNOP>QRASRTRT>UVHNH>BRW>E>X]@]@X>^A>X@XEX@X\>>>
862
7$1$3
378862921$789
98244
572$1863224733
222$38
>>>>]@]@X>\>_R`RQR>aA^S>QRASRTRT>bcRAR>>X@XEX@X
2
2
9786$
9
3583
3!222$38
2869
12
323582
2
2
27
>>>>>GHIHJK>L>MNOP>QRASRTRT>UVHNH>BRW>E>X]@]@X\
>>>>>dHIHKH>MNOP>QRASeTRT>UVHNH>X@XEX@X\
0$373521589
$249
289332223
2
2298244
$!68
7
32
222$389
356789235852
31
6$7
01
73863
834$78344867$3$#32326
$!680f738g3$9
97825$
582
2
225$262
54473863
$
23582=
hi
8!2
2
2658867$33863
8j2
15#
26458$3379$352158
$!68k
h0123456782#173=242%3331
729
737
2
$!68998#
385729
737
23863
8
h0123456784239
583863
$46!8186
6
$
78
3
2621234567821239
8
hl4867$32#1732692537"8$186
!
71
7
$!68
0123456789
3863
8
01239
2
6828682
78
633721239
2
68
!"#$%#!%&'#"$#%(')*+(*,+-
./01"$%#!-2*13%!%$4#!1 &
05677318626
381397733863186:;
212345678<
3
3863
8
2
2
287=8
3186>05677318623863
84
81
=822
?2865
?23@A?9=8=B38=
262123456783A22
3232
53==219335
2:9342
?966C
>D65
32
476398B3?23@A?9=23863
9678638C3233?23@
A=9828
=86<
983C5
?23@
23863?686;
8=8
63
>067=
3212345678
3223
23=EFG5
9542
?3=217A2?9
34438635
2:9393787
5
?3
32327>0386371B3582
3325677332
43
3?3267=
35
2:932621234567842>0
56773186
72
3
6:939
429=
2
?23@
886
03863
?67=
32123456783232
9?23
9
6
8
H59=2358262123456783232
9EFG5
954233
738?67
326EFG
5
954@
33788623
38
G?38=3212
359
321233232
2
4233
8A26
;
46212345678
5
2:939
886?289
B3582
056773
3186?2865
232A23863
8895895262
5447
:8
3
=37
>0123456785
2:93933232
26@EFG5
95
86B38
I>0123456782
3C5
785
2:9352
73
8
J>0
3335
2:939
4@
2
75
28639335
2:9343
38EFGK4
2621234567842>
>H863
C3233582
L>H863
73
8
06EFGK4359
321239
43
3832
31865
32
3232
269335232428H83M28
98635
9
863;
A22
837:NO3@1C852
=6?38;
>
0
3
6
4=7353C323C
4256773?2865
2352>06
8
:82621239
23
B@EFG5
95N:
>7:C3>P
O
5
B3582>06EFG5
9586
6326212345678
86
6333;
67>06EFG2
9
3212363232
2
2378359
82273262
5447:
12
78C32382
QQQQ
QQQQRSTUVQWXYZ[\]^_`ab_QX]c\d[]e^_fghij_Sk
QQQQRdlmlZXmk
QQQQQQQQRV\e[]Q[d^n`nQXUoc\dX^npbbqnQV\e[]]lUX^ncrl]dl]nQ
QQQQQQQQQQQQQQolZZs\Yd^ncrl]dl]nQV\e[]X]ltVXd^nunvk
QQQQQQQQRV\e[]Q[d^nwnQXUoc\dX^npbbxnQV\e[]]lUX^ndXXolynQ
QQQQQQQQQQQQQQolZZs\Yd^ndXXolynQV\e[]X]ltVXd^n]nvk
QQQQQQQQRvdlmlZXmk
QQQQ
QQQQ
0
3
6
:842
3186=3M9z3793@1C85
863;
2:z89
2393
:B3;
72z
212345678?96
0123456789
3863
8
!"# $%$&'( )*!+
$, $, -$, ./01&21.13 4,.5.#2'6
$5$-
#7%.%$&25813 4,8,, 8
99:;!! 2<22<22'6
=(# $&5$'6
>
06?@AB4C35D9
321239
2343E
3FG
2621234567842H
I((,, /
!"#J%#J&'( )*!+
,#J-
(K,L1,#J& .%$, &'.%$, I&'.
%M =N J1&2!=.*1,2''6
=,#J6
>
O63
EP3QC
7C1R3S23T
243E
3E3332D32
9US96
2VW89
T1T2123456783863
X
YZ[\]^_`aZ\ZbcZde[fZc
0g83h9UV
3
D3DC186DijE8863333863
EDCj633476398R326212345678
3863
8S6X0k763Q83DU
3E44
G
EC4E6Q3863k
2123937835U9i23
lmnC
W79C5
783863H062
2
U26589
opqk
G
3C
D863G
W
F22CC2
CQD68r
S9ij2
D3knC
W7T
P2
T42CFT
Us
E1C
BX0386335U9i23585D22g83h9UV
3
DC186D
S3Q8i3212k
S286C5
T7
6
QV2D2CW89
tiDr47
C3js63uk
Fij68D
8
8Q447P78862F5386585D2X0
Fij6333P
Cj8i
8Q44
E6P3
CG
78
86D
863S3Q
84QPR3S3Q
X03863
S6
CQD687V9C39
E3S3Q
r2S9
2
7F
E
3
94F
3nU9
D3
E886S289C
R3S23T245678
C3
7F
E
3D3
X
vwxwbyzc{b|b}Za~{[fdyabb\Z
Zd[
Zbd{`afy[{
X
0123456789
3863
8
8386306898635
9
3863
83869
5
91
886783863091
2886783863
168
83269
368367
0
3186
3!83212683863
1
2"
65852826
1
24567821239
#6#3345
$3232867
5
3
78
986
5822(
#187"223
25
6237
2")89
2327
'
84880386321239
2"
6585
863
63!2
1863
87
22
378637
5'2
0123*9735
33860
3186
3!832123863686
884!
21239
23
95
5852863476398$3
3
386321238935
)27683588632
284!212389&958
7'
#)27682782
+,-.+/.012344.23564732
089:388
3186)
'2262123456783
873863
68
8
73
8
23592358203863 2'358
"872
#3
6!"939
4
5
2
0123&958
7'
#
826
3'13212345678)8239
2865
2352
26213&9589
86
8
#
3!
;'83863
3 96582
2 2'321:<="22)89
7'
#
8
2 2'358"2237
21582>"
783
8865865
2
12248652?
23863
&33235820&3323585
3#44 2'3587178
3!035923933
619
8998"562988
#3
41633 2'358
1
3
82
31863#443
'8$3"22378359232&7
8
8354
562398'
$383869
5
3232&3358721239
03"223
#'67
0123456789
3863
8
!"#$%!&'()*"+,'-.-/0"!&'12!"(!!(3
45
2865
62123456788723863
689:
;79:2
735873863
621237:3<=735873863
6>1
773863
63=?
873863
6?23
9:@85<73863
A/B0%*C-DEE'&F$FG2--"-.-/0"!&'12!"(!(/3
45
2865H9
9623982123791
6823863
88
<@4
I3>5
27:19
J3863
K5
L35822
L>5:389:
;7J?96
423863893323582M?287
=853
?33=:72
I>3
6K89:
;7J=28L<@>7886226
N9:=2M?2:787
=O
39>544
N82PN9:3=2
;2791
7J198L3582<@
7844Q
6
?3K7=3
4:
123863893323582M?287
=853
?33=:72
I>3
6K89:
;7J=28L<@>7886226
N9:=2M?2:787
=O
>78862N82PN9:3=2
P-.-/0"!B0&"-&')-R+&*&'&"G'SB-!"T'!(C-12!"(!!&)03
45
2865
68U
863K7
I=:@63V1>
9N7:382:149WX5
6N=9U
37:3<=5;7J8
I=:@63VN=9U;37:3<=2379:82:149WX5
617983=5;7J8
I=:@63V17982:149WX5
64>63873863
I=:@63VN=YN=919;379:38382:149WX5
6O677Q
8
I=:@63VN=919;379:X
Z*F+-"*%!&'0-').'"(!)-.-/0"!&'!(-+B-'&"0!
1TCC!(C!"[B(!()3
45
2865
6:637354
5
6\]^__`]Y
635=9 3 U5=589
6867:9:L7294U
3979
a!"'-)&"-'-B(.*(*-'[)/3
45
2865
0123456789
3863
8
82
2
265886733863
8
15
26!379352158
"68#
0123456782173$24%333&1
79
737
2
"689'98
385'79
737
23863
8
0123456784(239
583863
)4)68'186
)6)
"&
78"
3
26212345678
21239
"8"
*86732173269"5!7+8"186",
7&1
7
"68
0123,9
-2
68$286"&"82
78
)6)3372123,9
-2
"68
234567489
!"#$%&'()*+,-#%./0(1&2+34'#%!'5!061!789:;<=>>1
?@:7A!1%+B'(5!)+B!5!C&DE!)%+.F+GH#EDC!89IJ9K=>>L
M8:N8O?PO7,Q%&E#%!-+B#%#.#1!+,DDC($#%(&)1+%!1%()*I@8P8R8@=>0>
01
123456709
6553
6665
6
6767
333
2665
235
5
5
266
6265
6
66
7
9
23373
!67"
6
3
2
6
66
3
23373
6265
335
#3$53
66
3
6656
4
53
5!#
3
2665
3
3
#3$5235#
%23
&3
3
6"
76
3
25
37
6
6
676
2
676!'9
6
3
(6#6656
6
3)
(6#65
56565
535#
69
*
+*
,-+*./
.
5$
(7353
37#3
5056
3
3
3
(63!355
2
6
75
6"550!
76
!675
2
576
6
6
66
1/2
1*
%1/253
13735
*76
3'9
*
333
6
3
!6
)
576
3)
75
#6535
#66
$5
6
669
*
76
!676
565
66
4
5$44
4
6
665
6265
6266
%75
3
3)'
366
!66
6
)
3339
*
6
67)
5
4#3
6
67"56
(69
*
6"5
76
!67
6
555
333
655
3
152*
/1
56&2
)35
23
9
*
76
!67
6
3!3557
5475
23
3
67265
4
6
6
537573
3
152*
3
67&65
%
5355'
3
(3
575473
57#3
3
4
6
6659
*
3
!6
)
6#66
$5
33
562
%
$5
(77)!4
73(3
57'
76
!67
6$56
466
55
&773
9
*
76
!67"
3
2)35
&)
6
$573
6
546
7535
75
!!683765
23
9
975
6226
47
567#655
%/1
475
0
(35)
5
535)
6265'
3
47#65
6!6567
3
7
76
!67
67655
23
59
*
7
6765
6
&46
4
36
23
352
6
5
0:
63#5
333
"6
%&46'
76
!67"
23
3537
6
656
6
"
67655
23
%5353
3
35$
3335'9
473
2
3
53
$5655
567#65
3
2353
6765
6
67
6
5!#3
23
9
53
676576
5
"
36
46
(5
3
562
75
5676
9
*
1276
6
)!$555
67)#3
46
6)73
5762
3
45
3
65
7(6$
5265
6
$739
*
6
5625
6
6
(5)
6
5
6
537533
9
*
6
!3
6
54
73(
67655
6
466
5
675
3
#33&745
5
62656
6!
7235)9
;7
3
567
35$3
"
352355
<
=>?@
=A*1*
>@
=,6752
,67655"
3
23
3
333
435(7
("656
675
3
,67255
3
6
76
759
5656
353
334#
6
3
)!$555
6
46
A33
>@
56&2
)3
23
3573
75
6
5
35
3
>?@
6
!3
56&2
)5
33359
0
012334567895
012334567895
62213172373291423245147433
6395432131397
2717323731
4823!614
32"272#31
27$
4%&08
5!25823!61'143213"(5
325297$4545
525252827)734794532(4511$32132755277*
3+(
22!85
221
927
2122712
1,2
32(21
!531$
2
427232157
(3273!65(4
(
11431
3254!#6(
1-
141
2327258.(272335
3
*
/41597#6
(3272234
91*448322$52882"27270
5
223#2712$823
7
25722301(45(
114"2#325
4
-
4*53127
3$931
,235
312+31(27"
2723#2
"2#2133$
(3272723213
4!2821432135*448322
35281(251345147824!5
$
41597#627
2332425*44832223$823
7
25722301(45
6#4"!+391577"633435
750*4483222723245147433235-
5
25823223#$'14"27277(255
2
6#"6391
5"
69'
3765'5"
6-
43
58$827
5252(2932139:
012334567895
620
13213225297914232451123127
43697
14483227124232!!4772"23121#4827
23
!282143213227332
12
$7415
12739$75
%
0&4872'()*3213123(+,-.5
2#48
$741144
'/044832223
1234563789:;<=7>5<?7@3AB8CD7AE65F@7GH=38A<5I7J7
7777A3@AK5L87M7NO@A3LPQ3AR65836AOCSA3@AK5L8TUL3SDV7
W
7777777777
X4432132271.732#4$-63341164$43Y63343"43652
3213$1Z
397
+*213
72#[26*213
72,#4
4$\23"2343$112123
1+*213
]$\2^3,
62_0
1321322!85
52474423245147433
)5329^
13213+`4^361,
'44474ab247478491$3213271255
25272"234`4^Z
361+4^"2,32827#4827
"43$5
22325!124
5329^
1
2
132132-6334391942
1321327725
42
21$\2368$
012334567895
27
21
813
2
528
27725
4
2368
33
27
21
41
74343
2512
4
82 !272725
2
"338
2368
4739
#
1272#312
2
12
14
4
4
!7243
277
4
82 !2727
27
2
89175
4!61
!27"7237
4
230
51
1
4
$2
2512"25
44322125
!63&4
1&2 2125
752
4
3213
21232
4&27
33
4
3213
21232
4
12&2
7475
!6354
23
2
13
12971
4
41597436
5"
93
4
4159743
21232
1#3136
74&2325
3
72231
&45
3213
!633435
#5,
/
$4361
3213
21232
1397
43
41597&4
827
2
72&7231213$412
4
12&723
82
%93372&723:2;6213
93372&723:21512
93372115
72&723$5!
72&723$532<3
)
'11213$412
4
'78
82
%84 2$5
32<3
'1=32
)
1
4
-7321213$412
4
-732
82
2368454
27
72512
%-732$45
-732$5!
93372&723:2;6213
93372&723:2
1512
)
4823
35
72 2125
12&72353
&4
!73253
!6334365
4
>247478491
835
?94
895
1
'@53
3213
2123223
4159765
48
2
$4361
3213
1
72323
41597
72&72312137632
844511*7
!633436
012334567895
474827
)4
#9)7'7
2
&2
2'3
4159765
071
7&&1&53
8917)6
4
82#2727
27
2
4
44+361
)4
#9)7)437
8&3
72231&
456
4
4
38+43
7
849)94
8917)6
4
+&73345
4
32132725
.247478491
900:;<=7
8494
271
82 791
43&5
4
125
2
)4
32132725
.247478491
2123&5
)'7
3272*325
277
48
761
85654
&1
)4
27
#74791
4
933&397'5
191745'
)4
#9)76
+4+361+2
+88 51+2+
+88 5133+7253
+88 5175
412+3)3)4
)653
$
433'7
#/
827
2'3
41597)6%
06395
8' 1*316
4
=+5#=.287
5#69+'1
977895
37
2
>4
8' 1*345
44)6
474827
2512
5#69+'1
97
7895
93
4
8525
8' 1*391
2733
82531/
27
43
47487
25
32)213&1127
7
2
9368
63'3447
2&1*31/
#9)7
34
3478945
1
*)6
2
82)2
&1&53
&1
8&3
8' 1*333
?)6
2
4
232
2)2
&13
4
.24
2)2
&1
272)&2
44
4
@.2
4
A
223"
1
63956
04872B5CB44+361
127232
2977*3914
2 8+43
25122
DEFGHIFJK
LLDEFGHIFJMNOPFKQFGHIFJRFSTGFUJVGDWEFGHIFJMNOPFK
LLDEFGHIFJMUIOEEK
LLLLVGXYOZOU[FYUOUJ\EYEFGHFGYQFGHIFJ]FEJRFSTGFUJVG
LLDWEFGHIFJMUIOEEK
LL5DTNTJMZOGOPK
LLLLDZOGOPMNOPFKZOGOP^DWZOGOPMNOPFK
012334567895
368
483297734365435
722115282272725
4827
5
7251747563
8273343213726354321!363955
1!5"
354725174756372#441!227475528734
185"
2527725!1122125726333$
27443449741!27725!1225#$
%4&3612
'(
)23685221!37393)441341!22747
79)954
84)472633311!43472517474'531
748433
4*232!99579343)6+
,62-.-%4&361321!823/6163343919547
48434
%4&361"4541!59743)6489821!338'7&3)236843#'6"
7614433489)945$0!22
1!2&1441!227475732!
89172517475127232%141!227478'7&3)2368
412115
02723%532(314''2
&50!241!59743/441232'#$
4
3213#$14324345#$823/6145#52841!59743)647251747
"225
8233335677$572517475141!59743/44266213
#25$
21'512#25$711!22!28)2368732!
827
24
*232!2+
266213 04)9344''21!397
484821!33
933'02723:2662131!397
/71!984!
;7347945 4 25#$ 823/6145
41!597)6
29773164321!31
'4483223
1413#2$3<95
823/"
6114725272!
4855&144
"
895
1 1 )236845
2!2 4
321!3271'4483225242977391931!7"
97)9+123:2832=> 211#$
123:2832"
913<482#$
123:2832212#$
123?23#$
21'512 0!4821!33933'02723:21'5121!39"
7
2
'795
4
&5 04)93 44''2 1!397
48 4
821!3302723%51!397
/71!9"
84!@223123!313
5&47"
!97/'448322234)68241!272352
012334567895
2
87577415974325973761
8236112353448232!"#123$2%723&
'482!"
$2%723(5323) 42 '2823*27+%237257#26,
45-&
,
732.+5141597434.4%4173/
05,,23$2%723(5323!"82361%114&
3132
12115 /2512%9734374589
452723*%
321!504797.4"482,133
.23683
/3213,,%5
254191185
4159743.6#84.27725*23.434&
347893
'582,2,
17232341454,2$2%723&532132713%,*
22131454,2$2%7231397
7
04872343(4036112%723321321231397
!1723"
5555
555556789:;5<=:>58?@:AB=@C7DEF?8G?H7?ID5J?8G?H7?IDK
5555L
55555555MJ?8G?H7?IDNO>>POQOR?D?QEST7A;D:=ASU5S9=@=7DSKV
5555W
55556789:;5<=:>5D?IDB=@C7DEK
5555L
55555555XYOAO@?QZ?Q<9?D5I?Q<9?D5[5A?J5YOAO@?QZ?Q<9?DEKV
55555555DQ\L
5555555555554I?Q<9?DN6Q=;?IIG?H7?IDEQ?H7?IDU5Q?I6=AI?KV
55555555W;OD;]E^_;?6D:=A5?_K
55555555L
555555555555`TO:9ES^_;?6D:=A5=;;7Q?>a5S5b
5?_N@?DY?IIO@?EKKV
55555555W
5555555cOII?QDdO9I?ESZ?II:=A5:I5?_:ID5\?DSU5
55555555Q?H7?IDN:IG?H7?ID?>Z?II:=Ae>fO9:>EKKV
5555W
55556789:;5<=:>5?A>B=@C7DEgF?8G?I6=AI?5D]?G?I6=AI?K
5555L
55555555DQ\5L
012334567895
aUbH>48=52A>34C34784F5=>A277>2O
>C21B?512>34O?3H>48=52A>4F>DC3DA2>c>A277
72O
25K>ZQF>aUb>M27@?7O?F91>3dII>6341J391IW7>977H>3dII>72E23V1DO>=1>S45K[
Q>321F32A>M63343919C4>AD3>72E23V1DO>=1>AJ597A?F=AK>e63343E43G6A>2O
>891=A>1F^
2CS723>M?C89G9I45H>S4O
>]f5=3>321F3I2>9O
4FS4>ZG2725>B=774543I45>4>]f5=3>T^
21>528>398?O43?33[K>gF2CS723AD53>M63343S4>E41F597565A>A277>4>3272BJ3233>C2@=^
C2N3?C>1F2CS72323>82O4@S4>52A=>4>321F3>?1F397
65A>327G21>52SD3K>Q>S9741F>aUb
M?C89368hH>@2>4>i4N361>?7@479CW7>723d73E23R5A>2O
>`71>M9G73>E?FF9H>JO
>A=82523
E387>1FdS2O>721FK>U=6395>27E27
2F3RA>4>j2I474A4784F91>O
dA2CDI2>4>723d73d33
`17^3>4>ADCD1>4>8=>2123R5AI25>4>AdS23A2FVADBB25>5DF>A=k
0`48B72lKXKli4N361>1F2CS723>321F3>M63343914>Z>1?C[
/m*mn1n1.$:9;% $o
%!%-p-/ $07-$:$-$:-9 $.$:q7!*
$/$-7
012334567895
27
439194415742285
343478442
112131314
4
112285
21235427
372919318252324821
23!5252
4212354232"##255$
%62&'&(4)361127233213!52285
2451"25
*445)1174
+232451477,633434-.,3/%01427""3277
21325!52
845,!55
27$
0248#72&0&(4)3613213,63343914,633434347478491
,893945
444456789:4;<=<9:4>?9@4A=9BCD<E9BFGH4=EF;I4J
44444444K6B9<L<MN<69LOM;<P6BBMELE6BC;69<MCIIQ
4444R
,2535!72977343364(4)361#448322348"72
3272"
155)1474#327282233322977391437223"11597$
ST
#4483227U#4485V3
WX5,69)1,93745827
52522)4)361##232148524)7411
#434527772552Y32,59743454U)4)361)5,V)$Z)4)361323
ST
#44832123127
3213 45 4 82,2727" 2512 973 977391947
.
1328123*#23
-1
[7
25482523234432132285
22374#3278223342121
8-\\1
85254)34825232-4#)1744122747
87
2513!72787
25#448323977321
]6152512
]61525125283213474784914528,7
484315329)1
474784914822542123252
^247478491.2312746
012334567895
3
843973457223
23251328343432797734511
27
2539
75!32872232!
!48
"5
397#4!
4$
72232!
47478491$%
682539"4!
#98484
238252327223
74232544
2328252%12712
39732$%2#987
255
27&
232#2977343"3213214#43"25%1242321
7!9734391
43
5
'34(
)63
84361
%391$732
9125%127223321$
!
1*1!
2123582!"#974732
543282349
13
334515318425
398
!43
33$%2#987
25*7147478491382!36%5
)+2132123263343914
%3916395,
%3916395726334344953
3213223$4827
27863439111312$272572!-.53/+213012
3
43398
!43
)33
13442741597"43$
!
85%256!
45434 !32823
41597442597.562343287237312$485%2543415974$
4
!453973$
!
52825!252*75#2"425%12#25
)63
843613272317441318252321221
73$4
41472
47849133272323*!72!2127
2
),2741597"8252%18253$
!
$
!25%12#252741597"43
4365732$84%%2597436$
!
827
232587
25
8&27232234343!202745!
743625%12*58&%13
)62231!235
'3$
!
4!2##2"43172373211*32977343"$
!
95
63
71"4748255
4!
82%%!4%
33%9368!2"33431
5
82!425%120242"#98
72373232$131*825232
7
!97
$321322%85
282!3253232
)63
843612"2325%12!
27125%12521152277
7255202382!
7%914%"%(
2"232%285
2432813152
7
4843938 5
212354
883
13#2#2436$
!
282!492#472
447849134112"7212%12$84%432827977391949!23
4!
6747478491
12!31!27
:76%1
5!
27%7%242"233$
!
33532973
91
;
534#12&2582!72234%52!
2213$4827
37*!!25425%2
12!
2742"233$14'2"31727$4
72
4$84%
2713432823
)627/<=*2523*7%11221/1232725
%39121235$588398
!4391
)>
843$5511*1!9334%43#914
)898
176!5$4827
12!38659543
012334567895
212343423231821986544725
2782124144
13761!67422"13
7213#422$3%&73'
23732(91954
8252324&232)*
'+23)448322524824914',33271)14542352&3277
8245'
-'./0.6$2/2045428253%44832229773914'01&5"3
(4159736548(223233765"4&454251252'0&2741&5
397116
4545425&73
97153253227439713'
3'42827)977391954824914',334682432827)977391954
531825233'0&2723254534745232451453"3(41597%
48346615"4323376539843'
7'0
1)88&27232448322524824914'
'93213122597914444832252429773914'
23234&232)297739147(36732*
4472:''
;43214 +44832 93
.6$2/204542".6&215 72*<<<&4<7<1&5<382=3<365
8253 8&276
4545412&225
&73%
!67421 +77./0 >>>>>
!67 ,5&2
53 !67?72*@25380=3A,$23<
67'=87
,5&2
53 !67?72*@25380=3A/537<
67'=87
,5&2
53 !67?72*@25380=3A.2&2<
67'=87
,5&2
53 !67?72*@25380=3A471<
67'=87
+13"67
$351
$(&23(243"?72134$(&2*><13<>
4$31
0"84753$4"B2$2531*28474211
35
0227429773914785252$2527725)4251241&5443"
39431(4&9739131727472(42
79718917434482
82(&4445347478491348732(444#472"43125
7263343446533213223'644391122124321325284891
15527277432823(4411221&7348253891147'0525
212325225232327429773332847$8212263954#227272325
27(23)172373(23)411211221328&21'
012334567895
725174732132712
7251747321327123179777251747743213271248
4827797743954277251214725174712439195427
72512182
412274745545114!"549741483
472512739747945#$%5
252182791432213&54814!51
'72(32527125
21$0
13213219818279173245
45)27&723321325329*+13213255*1!272577454345$,223145
-272568.43189132132)633439194222532132123232212
872825397914!2725319)/3915
27$'72(25122522233
40(325470532)4*234812/3127'72(47+77223!441*32728223
4159751114)271433488659*+$5458525212325
52&527782/5654823+614348232527
2&54&779)27$
14554&72382791547467+5
25218279185379674
'72(%52
487
45*184341597423+74838227725
5&5$055212/3127"55
25)27/323!&127223!&45329
*+11)27&7233213!2523$
725174752742
13213$03311981
82791/597'72(2535
73)913#4834'7212272/3233
867!4139843'7653482
115329*+13213223121
2275$%4'7653251239741333682312/31277223823+6
14341558+5/539843!444)612728220485253#
3213271332131225*94312)59743655329*+13213#5%,
8252323139843!44638439743+661545329743+#41597
43+53251227$
0
13213
72517470
17)65*5971321327123"7223114+'72(
253'7653$
'76533272/3122
1282
48+"5
3943277*14723"7325&5
)7653$$$19*4838227745654)/3+541$03'741:22721
2352
12889179184!4!84)9!751;<,4
;
445**1473223!&82$063954)918(87)9!71/312195
4159743!64"5
3945721397
43$64157+454=253331
1397
43277/56584!443)633435$,2231454)61450>
'741#4
443221)27&72325)633435/
7223145$2
1321323
3
/3!&)27
43213823+61527725&47487
25977/391
27
2113$3213823+614543213212322527
225227482
1841397
4<213441272198433!4$3213)&5
25282345)
89*+431)823&54)&5
)2!72*22733$,2231453"5)89
*+31824572/91344
10:3983481&121$
0(4872?$@$?%2345)89*+824919548+!44'7633213
2123)&5
2
ABCDEFGCDHIJKEJLMNOBCDEPJDPDQKKLDCGPEL
PRSJTOUJDDQCVWNOXXYZ[[\O]^
012334567895
!
"#$76%3#&25'1(2Ԉ%7
25#8)'*5#528#+*&793*((4#4#72,231-.21#/4&48-32&2+
520-3#-1#-&3-+-31#"8%3#82.4'65+#4(3#+%#2*.34#4&5%#4(#511(2143-15-71#633#%1
,41(597,4336+#4#82.1(*+*33#1237/89#-1#324&:*;589#823)'61*+431#<73479=45
4#1237/89>=45#,*((6+#7-3&2#4(#%'?(43?#*=32+368*3#8@%82&9A#48%3#4#324&>
:*;589>=45#729774365+#-1#4#&222&25B%9393#5677>&4#9774336+#82(6395#4#1(28-3.
C33?
2271(4=4'4391#"#321(3#+-1(723#8@213D6%39#*1(397
#2*.34#511(2#4#321(3#21232%5>
3+23A#48%#2.
#9734765+#'22%5%973#*1(397
#8@213D6%3#721(9&84(*333491#"#&25'1(2&
84.4#'22%5%97#2.
#$&482;*&+D6%32>3A#48%#34&34784(#321(3#21232+23#8@213E412
*1(397
*+439#4827
2+#398*.4339+#+F755=5(?#34/61G#321(327-13#%1H#41(%5+&*5
321(327-1A#227,41(597)%#227F723#321(327-13A#13=1#1#"#223721(3-1#47433#1(F+1-.
045#04748%7
25#.&42%+61#321(3#263343)#47+4784(91#7-3&2,*(919&4A#-1#4554+
,41(597439&41#D(2&25B1-&2#4#$76%3#34&34784(#2.
#"6I#47+4784(913A#4827
#72>
26334334#4#321(32+23#843'#8634334#4#4(#2&2'8-5
2+231#0,,2(#4#723573,23?#D48>
/72@213I6552J87#29373#+277#227F74&565+1#0552+#4#+)'34#4#+5023+2(?H
0J48/72K1L1K"#$76%3#.&42%+61#321(3#263343)#47+4784(91954+#+)'34
MNOPQRSTUMVWURXTUYZUO[
\]^_`aabcdefcgh
^]bhi_]^Tjkffa_llmmmneogpqndg]lrsstl]^]bj
^]bhi_ubvchfTjkffa_llmmmnocwcfebaxc]efqinhqflrssyl
ubvchfj
zbe{gvfTjepigbvfqj
dxqefcgh|g]abqfqTjifexf}qif~xgdqiiqqhfj
mcofkTjssjkqcwkfTjssj
\]^_
dxcaf
MW\|`}`
Q
S
RVX
SQRVVRVSQRSRVSQRSR
Q
SRQ
RVQ
RR
Mz
SRRSRSRRRR
SRSSSSTRSS
RSSV
RQ
RR
WRRSVSRRSS
!
[
\l]^_
dxcaf
z
\ubvchf_}qifqivbfciabe{mcofkTjssjkqcwkfTjssj
l
012334567895
!"##$%&
'( 4))*321+3*,-1+723*27.5/039141
2 3*421+3*,-1+7 23*5)(2,36841
3+*67*21*1583*455
.1+58*,277*829.18-3275.*4*829:2727;*627<21*5)(2,368847
4=95
*321+3*,-1+723>5,*?451*@.6395*27,-1+03233>,*4*829:2727;*321+3*:63343A
984:.,61*8B87*:9(73C*:58/0316,*72*4+*47,4784+9165,43*D9
C*=59
*2+*4*:9(7*4/(4*4+
47,4784+9165,*:;*4)74,93*6E741=F2?275G*47433*2+*4+*37H4
1*I58G.7271*E63341<
16,*4*G85(2,323C*2+6395*4*321+3*:63343A*4)74,93*:59(6,*7935.C*4827
*4*=933-8)25
72:63343(4*4*321+32,23C*84(/*829(272503.*4+*282/8-5
2,231
J84:.,61*27282,*321+327-12*4*E76.53*825/1+28827*72=231-921C*/2*1+9851*/575<
984*5/4*,277*:.9
275.1*0+*?47A(9)45*898*.532989K.A1*321+3C*48.*4*825/1+28>5,
29
>338L,M/-1-3*321+327.1*N18285>5,*,277*4*E76.3*72=23;1-92.3C*,-5
1+282<
.3C*8283*2552,*36/439)45*,277*4+*282/23.*825/1+28*.1*27,-1+0325.1*3*?2+-8<
7;,*528*(272552,*829*8M93M5*4*:27=27
2+-1*6395C*-1*4+*9774G536,*128*721+
4+55547*=27
21C*=4528*3M))*.5.K.47.+97A*8L?272323*?-92+52,1*0+*,>7M5)M+;
1+9803A9-G25*,>7M5)M+;*./2.9*3483=431*3*321+352,*8.5/25,-GG25*829*,277
?985.*2+3*4+*27;82*528*829(A157=43A*./;31*0882*4*825/1+28*82957/913*,05971
@.5/4//.9*?98565,*,277C*4809*29
*?2+-87;*.5.K.47.+97A/533*-1*=27
2125*829(2<
72531*3+*41+.5,855*123OG67*-1*4+*3248F5H567*:>99?-5
2,,27*2+3*4*G85)7-893
82957/=43(6,1*P5++65,*7-382*49
*321+3*212323*84(/*?-92++>,*27*4*,M?23,2+;
7-G-12,23Q
0B48G72R1S1RJ84:.,61*2728*321+327-12*E76.53*129031-9-?27
TUVWWXYV
ZWT[V\[VY
]^_\[XT_
`V[aZbcdUTXY
e
[Vf[g_Z^[
_Vh
iVf[g_Z^[bcj
2[Vf[g_Z^[klYYmUV_[nX`[V_VWbopVfmUV_[kqrmsigtuvqtwxnmimy
zl`{_\|l_YpVWb
}ZV_Ya_[XpqT~ZpV[Vy
cy
]lp`Vy
y
[W^V
cj
lYYqXpYb
[Vf[g_Z^[
cj
P5++6,*7 -382*4*829:2727;*984:.,61*?2+-87;3
2 3/( 65,*=5++9*29
*14(93*2128-5
*:.9
27;3C*4827
*4*7-382=5+91*?-9-5*:63
84(/*72
z P41+597 (6,*4+*41+.5,855*:.9
27;*30G613
} P41+597 (6,*4*E76.3<)45*/2:.5.973*:>99?-5
3C*48.*528*K1.597*1288.3
3/( 6,*=5++9*4+*4/533*?2+-87;3*4*321+3*,M85
2+23=2+*6421305?.85582537
3+*67<M1*7-G-15-7*4+*4//I=.7/*:>99?-55
27*=5++94/(6,*4*984:.,61*272823
4*321+3*2123=2+C*48.*:68K1954,*3L5=231*3*321+3*2123*528*29
*984:.,61*27<
28*6ONI58G552537C*/2*825/27,2+-182*977*4*:4
4/2*328?2+-1.*8.534*4*=27
21
8L,M/-1*-8/2,-)251*3*?2+-87;,*4*828A8.9)45*7-32+52,*.5.K.47.+97A/54,C*/2
012334567895
48
5284647487
253975345252872152474827
27
28
2822528637242725274
63!"5
45288#$
5227
2125%&321633438'7282539742341'2(9712
2853934
8524522321305582534827
4$232!"5
2238'72825
39744321327"1"2")25*
+47
+47&3
+2827
+2827&3
+282&77725
+237&3
+237,
-482
+237.52/
+1237.52/
+568725
&3213212372639146395822771!5323548277"4391434447"32
332"7372277125427!7237"127727$753$7"12827
234
$23247"23!527*
0/48'720%1%0&8277"43913821!532332423582361
447632512)25
567899:;85<96=8>=8;5?@A>=:6A5=8B9C6DAEFG76:;5H
555555555555555598I678JK:L;E5=8M=NA<@=5FO
5555555555555555P=8M=NA<@=5Q5A@LLO
55555555R
S2 !427!723
2271399)7T
P U7 7
31642225(9356774
843$74128"3
#34$232
47478847T
&2"7)2977
3914"1455427725 "124$2324772231"21*
0/48'720%%0V2"7343478954)2977
3914"127725 "12
5<@WL:>5?@A>=:6A5
=8X=Y8=Z8M=[96<89=\EF5G576:;5H
55555555555555557B95<BXXZK96@]KCB=BG^W_8>=5Q5A8D
5^W_8>=EFO
5555555555555555P<BXXZK96@]KCB=B`<96<89=\aBI85Q5b=8M=bO
012334567895
!!!"#
$%&' ()'*!'+
,%()'-*.(/0122&3
'45' +
' !673
8993
3
' ()':)144
;3
63
93
;#
<%&'%
#
=
>4
6'4!'
' !67+
)'?()'3
?1@A4
;?)!
B
C(D+
)'E
:"
F3
;#
=
G4
6'4!'
' ()':)144 +
?1@A4
;?)!
B
H6!+7' !'
()'
:)
144 ;#
=
I JKLL65MN 7O3P2N2Q
N2Q
1L2PRNKST2M368K3UN48VN39PK7T4N4NS2977W345XYNOP3OM23
4N82QZ2727[NZKP89S45\
]N^PK^2P3
_482N^PK^2P3
`47 62NOP3OM2VM23N977W316MNS2N4NMWa953NOP3OMP2\
$ ]XT 65MN2Q
Nb72c0a253d̀]ef0ghijjklN2128O5
NZVQ
27[3UN4827
S25NZVm
Q
27TnMN84TXN4N1VM2P21Na4Q
N1VM2P327251OQN3O5
O3d
< o25X27 TnMN4Na2LOP7[NOP3OMOp2LN4NMWa953NOP3OM23\
> q2ZV 5V97T65MN2Q
N823YX613N4N1VM2P21NOP3OM4X91N2123OP2\
C 07 725[PVLLnMN4NMWa953Np43913N4N4112P30r6471N823YX61N12QW31OQOa27\
G q2ZV 5V97T6MN4Np45X720a253_2a2Piss6PP2XN823YX613N4PP4N4LN2123P2UNp4N4
S2977W391N528NZ63K33N72N1VM2P2125\
H ]N 321L327[NM2P23P25X1L2P52MNMn7XTnMN27N4N1VM2P327251OQN3O5
O3N4NZ4V7N823Ym
X61Np41L597439a47\
]NZ6391N2P2X8O5
O3NQP4ZVM6145N27282Lp23TnMUNO1N4N^VPK1NPOQVYP4NM7VMM27a2
MV5
W7VMN4NpVS91UNa4Q
Np27
32725N2P2X8O5
3N4XYNZnQQaO5
UN827
23N4NMta23M2L[
9SP95N793p4365Mu
012334567895
620
132132285
524744