H13.2: Testing
• Introductie • Testing technieken • Management aspecten
Noodzaak van testen We willen betrouwbare software Mensenleven Economische waarde
Opsporen van de bron van een error is veel werk;
het wordt duurder als de error later is ontdekt: 0.5 – 3.5 uur op de unitlevel 6 – 10 x duurder op de systeemlevel
2
Test vroeg, en test vaak! ≥ 30% van totaal ontwikkelingkost (verschillende studies)
Systeemrequirement acceptatietesting Systeemspecificaties systeemtesting Systeemontwerp Implementatie
integrationtesting unit esting
development testing 3
De V-model
V-model Develomenttest door ontwikkelaar zelf Aceptatietest (aka functioneeltest) Opdrachtgever wilt een laaste ronde test dat de
product voldoet aan zijn requirement Meestal uitgevoerd door een 3e partij V-model ook toepasbaar op meer agile SDLCs Doe een V per subproject (Parallel Devel.) Doe een V per versie (RAD)
4
Terminologie Persoon bestel(producten)
System Under the Test (SUT), testobject
* bestellingen
test1() { x = new Persoon(…) V = new Producten[] { appel, peer } x.bestel(V) assert x.bestellingen.contains(appel) ; assert x.bestellingen.contains(peer) ; assert x.bestellingen.size() == 2 ; } 5
Product
• test sequence • test input • test expectation • test case • test suite • faal / failure • error • fout / fault
Test cases maken Per test case, twee componenten:
assert r == 0
Sequence en inputs Verwachtingen
Je hebt heel veel test cases nodig! Meestal handmatig duur Genereren van sequences/inputs kun je nog (deels)
automatiseren Gebruik dit als complement van manuele testing Formuleren van testverwachting is niet te
automatiseren Technieken: wit vs zwart, functioneel vs reactief, etc 6
Witte vs zwarte doos testing ‘testbasis’ : documentatie ontwerp en specificaties broncode
Wit je kan (en wil) de broncode van SUT zien Zwart andersom. Developertest is meestal wit,
meestal zwart.
7
aceptatietest is
Classificatieboom Hoe kun je systematisch testen? partitioneer de
inputdomein van SUT op een systematische wijze. Hypothese: SUT gedraagt equivalent op inputs uit dezelfde partitie. V leeg
Voorbeeld: V.isEmpty()
V niet leeg V niet valide
negatieve test
Per partitie minstens 1 waarde (input-combo)
8
(toch equivalent, dus 1x testen is in theorie voldoende, maar … )
Partitie/classificatie techniek Kan ook hiërarchisch. Student Invalid
addCijfer(student,cijfer) Cijfer
Onvoldoende
Bachelor Master
< 5.0
Voldoende
5.0 ≤ c < 5.5
Partities op laagste level heten “klassen” Beschrijf vervolgens de combinaties (over de
klassen) die je wil. Ook geschikt voor zwarte doos testing. 9
addCijfer(student,cijfer) Student Invalid
Cijfer Invalid
Onvoldoende
Bachelor Master
< 5.0
Voldoende
5.0 ≤ c < 5.5 5.5 ≤ c ≤ 6.0
TC1 TC2 TC3 …
10
> 6.0
Grenswaarden In principe, 1 concrete input per partitie is voldoende. Maar fouten worden vaak gemaakt op de randen van
een partitie maak dus ook aparte test cases. Cijfer Onvoldoende < 5.0 0.0 , 4.5, 4.99
5.0 ≤ c < 5.5 5.0, 5.2, 5.49
Zwel het aantal van test cases op… 11
Combinatorische explosie… partitie
Persoon leeftijd brutoInkomen nettoInkomen()
< 65
schijf 1
≥ 65
schijf 2 schijf 3 > schijf 3
Inputdomein A×B×C, totaal #combinaties is
#A × #B × #C Pragmatischer opties? 12
erg veel!
Welke combinaties gaan we testen? ALL : allemaal te veel. ONE: elke klasse minimaal 1x getest te weinig.
Student Invalid
Onvoldoende
Bachelor Master
13
Cijfer
< 5.0
5.0 ≤ c < 5.5
Voldoende
Welke combinaties gaan we testen? ONE + random, tot N cases. Gericht op combinaties-dekking specifier: @A dek alle klassen van A A*B dek alle combinaties van klassen uit A en B
@Student.Invalid , Student.Bachelor * Cijfer.Voldoende , Student.Master * Cijfer.Onvoledende 14
Concrete vs spec-based verwachting Persoon brutoInkomen nettoInkomen() test() { x = new Persoon(“Bob”, 17878) n = x.nettoInkomen() ; assert n == 10447.90 ; }
15
Product getGoedkoopste(producten) goedkoper(producten)
context Product :: getGoepkoopste(producten) pre: producten ≠ null post : result.goedkoper(producten)
test() { producten = … result = Product.getGoedkoopste(producten) assert result.goedkoper(producten) }
Testverwachting specificatie-based verwachting Met een stukje code die een post-conditie
implementeert en checkt. Herbruikbaar, en robust! Er zijn testobjecten waarvan de post-conditie erg moeilijk is om te formuleren (zoals uitrekenen van netto inkomen) Concreet uitgedrukt in een concrete waarde. Kost veel moeite om uit te rekennen Niet generiek Niet robust! 16
Dekking / coverage Testing is in principe onvolledig. Bovendien, je bronnen
zijn beperkt je moet beslissen waneer je stopt. Definieer een kwantificeerbaar doel, zoals:
Elke regel in SUT wordt ooit uitgeoefend (door een test). Coverage : hoeveel (in %) van dit doel bereikt is. Te weinig coverage impliceert dat je nog niet voldoende
toetst. 100% coverage betekent niet dat je software bugvrij is. 17
Standaarde dekkingconcepten P(x,y) { if (even(x)) x = x/2 else x-if (even(y)) y = y/2 else y-return x+y }
¬even(x) ¬even(y)
even(x)
even(y)
Control Flow Graph
Line coverage (vorige slide) Decision coverage :
Elke beslissing in SUT is uitgeoefend.
18
Standaarde dekkingconcepten Keuze van dekkingcriterium beïnvloedt hoe grondig
je testing is (dus ook de kosten). ¬even(x) ¬even(y)
even(x)
even(y)
Hoeveel testcases zijn nodig?
100% line coverage
min 1
100% decision coverage
min 2
100% path coverage
min 4
Path coverage
Elke executiepad in SUT is uitgeoefend. 19
Path-based coverage Path coverage is sterk.
100% path coverage ⇒ 100% decision coverage ⇒ 100% statement coverage. Maar, oneindig als je een loop hebt dek alleen 0 of ≥1
iteraties. Dan nog heb je potentieel vele paden exponentieel tov aantal van seriele beslissingpunten. McCabe: neem alleen lineare onafhankelijke paden
aantal is linier met de grote van je CFG. 20
McCabe 0
1
Set van lineaire onafhankelijke paden die alle pijltjes dekken: { [0,1,0,2] , [0,1,2] }
2 Elke pad heeft een f pijltje die anderen niet hebben.
21
Andere dekkingconcepten Dekking over de partities (hebben we al over gehad) Als je een toestandmachine hebt (later) : State coverage Branch coverage Of de analoog van mcCabe Mutatietest en mutatie coverage.
Injecteert fouten op een systematische wijze ( mutant). Je test suite moet zo alle (niet equivalente) mutanten van de originele SUT kunnen onderscheiden. 22
Duur! Alternatief: gebruik een gereduceerde set van mutatieoperatoren.
Model-based testing Tot nu toe: we nemen aan dat SUT ‘functioneel’ gedraagt
(SUT neemt input, en termineert met outputs). Reactive systeem: het blijft draaien. Voorbeeld: wekker, afstandbediening, verkeersysteem Specificatie in termen van input vs output relatie is
minder zinnig Kan abstract beschreven worden met een toestandmachine model Het kan erg ingewikkeld zijn. Model-based testing: gebruikt de TM-model als een bron 23
om test cases te genereren.
Model-based testing uit aan
[genoeg water]
entry / lampje aan
koffie
…
[niet genoeg] entry / knippert
Elke pad door de graaf is een test case: pijltjes events als invoer wat moet je controleren bij elke pijl en toestand in een pad? Uit dit model kun je test cases (systematisch) genereren: random gericht volgens je dekking criterium combinatie van deze 24
Model-based testing Geschikt voor het testen van een reactief
systeem. Grondig. Ook geschikt voor zwarte doos testing. Tools: TorX (Uni. Twente), ARC. Theorie PV
25
Overzicht (complementaire) methodes om test cases af te leiden:
input partitie en model based. Coverage kwantificeerbaar uitdrukking van de grondigheid van je testing. Problemen: Persistentie Concurrentie GUI
Testen van andere aspecten: Regressie Security Prestatie 26
Persistentie DB, files. Vormt een impliciet deel van de interne toestanden
van SUT. Problemen: Een testcase doet side effect op DB/files je hebt een
mechanisme nodig om de effecten ongedaan te maken. Interacties met DB/files zijn traag.
27
Persistentie Persoon ID naam
1
bestelt 0..
2..
1..
Product ID naam prijs
prijs ≤ 1.00 prijs > 1.00
DB is vaak complex, hoe creëer je een representatieve
DB populatie? Copieer data uit productie te groot traag Genereer hoe definieer je “representatief genoeg” ? Partitioneer, evt in combinatie met grenswaarden. 28
Concurrentie Een concurrent executie is gevoelig voor timing P doet iets Q doet iets
P boekt stoel 33 Q boekt stoel 33
Wie de stoel krijgt is afhankelijk van de snelheid van P,Q, andere processen.
Probleem Je kunt een executie niet dupliceren! Dus als een test case een error vindt, kun je de error
misschien niet dupliceren. 29
Regressietest Na productie van een software, moeten we de
software nog onderhouden: bug fixs nieuwe features
De modificaties mogen bestaande functionaliteiten,
voor zover nog relevant, niet stuk maken. Doe regressietest uitoefenen van de test suite van versie k-1. TESTALL : voer de hele test suite uit het duurt vaak lang! persistentie 30
Regressietest Je zou een strategie moeten bedenken voor: testselectie selecteer alleen een subset van je test
suite, maar met maximaal fault revealing potentie. testprioriteit als de selectie nog groot is, en je tijd beperkt is. Opties: Neem, per ‘module’, testcases die fouten ontdekten Random Mix Instrumentatie neem test cases die de
modificatiepunten passeren effectief, maar niet altijd mogelijk. 31
Performance testing Een bedrijf wordt afgerekend als zijn applicatie niet
genoeg presteert. Performance testing: je kijkt hoe de applicatie reageert op toenemende werkbelasting.
virtueel gebruiker
Elke VG simuleert bepaalde interacties creert dus belasting op App
APP
aparte machine
DB Server
32
#VBs (belasting)
Performance testing verwachte peaks normale belasting
tijd load test: om responstijd op typische werkbelasting te meten.
33
stress test: wat is de maximale belasting dat de app aankan?
Test management Groot project management is erg belangrijk. Belangrijkste TM instrumenten: testplan stroomlijnen van je infrastructuur software en hardware personeel en organisatie dagelijks sturing monitoren van vooruitgang afhandeling van bevindingen
34
Testplan, in grote lijn… Definieer de scope welke ‘modules’ moet je testen ? welke aspecten ? (zoals functionaliteit, veiligheid,
prestatie) hoe grondig (per module) ? risico analyse Som op de bronnen die je mag gebruiken Beschrijf je aanpak bijvoorbeeld de gekozen testmethodes
Anticipeer gevaren op je project geef een
contigency plan 35
Risico analyse Je bronnen zijn beperkt prioriteit stellen, zoals op
basis van risico en impact. Risico de kans dat een module M faalt. Impact de schade die volgt als M faalt. Je kunt R & I niet exact kwantificeren! schatting.
Module
36
Risico Impact
Prioriteit
M
1
1
1
N
5
3
15
O
3
3
9
Scala 1..5 (erg laag, laag, gemiddeld, hoog, erg hoog)
Bevindingen procedure Implementeer een strak en efficiënt bevindingen procedure.
Gerapporteerd
toegewezen
accepteer rapport
herschrijf slecht rapport afgewezen
goedkeur voor fixing
gefixed
tester wijst af
tester akkoord
bekeken
wijs fixing af uitgesteld
37
fix
herbekeken
gesloten
probleem keert toch terug
Bron: Foundation of Software Testing, 2008.