TDDI02 Programmeringsprojekt, Föreläsning 3 Anton Sundblad Filip Strömbäck Med utgångspunkt i tidigare slides av Jonas Lindgren På denna föreläsning: Verifikation, validering och testning
Begreppsdistinktioner Lite populistiskt uttryckt 1 : Validation: Are we building the right product? Verification: Are we building this product the right way? 1 Boehm
Vad är ett fel? I engelskan kan man skilja på 3 olika typer av fel: Error Ett misstag begånget av en person under utvecklingen, som kan resultera i Fault Ett fel i programvaran, som när det exekeveras kan orsaka Failure Något oönskat händer under exekeveringen! Obs: Errors/faults måste inte automatiskt leda till failures, inte nödvändigtvis en 1-1 mappning mellan de tre åt något håll
Validering/verifikation är nästan testning det med, men på dokument! Kravanalys: Kompletthet - Allt är med, inget underförstått Konsistens - Inga motsägelser Genomförbarhet - Inte bara rent funktionellt, men även ur ett affärsmässigt perspektiv Testbarhet - Kommer det gå att testa kraven, avgöra om de är uppfyllda eller ej? Skapa testdata för funktionella tester?
Validering/verifikation Design: Finns konsistens mellan kravspecifikation och design, beskriver de samma sak? Håller designen rätt kvalitet? (Företagsstandarder, etc) Skapa testdata för funktionella tester? Implementation: Finns konsistens mellan implementationen och designen, beskriver de samma sak? Testa implementationen, uppfyller den de tidigare satta kraven?
Validering/verifikation Testfasen: Testa moduler (unit tests) Integrationstesta modulerna som samarbetar Systemtest Smoke-test Alphatest? Betatest? Acceptanstest Underhåll: Alla steg i mindre skala, om och om igen
Effektivitet av felsökning Realtidsprojekt, 400 utvecklare (studie av van Vliet): %-andel funna designfel %-andel funna kodningsfel total effektivitet Designgranskning 54% - 54% Kodgranskning 33% 84% 64% Testning 38% 38% 38% Kostnadseffektivitet, samma studie: Designgranskning 844 Kodgranskning 138 Testning 017 Ibland är testning det enda alternativet
Statisk testning Läs/granska Låt andra göra, själv har man inte rätt destruktiva inställning Review - som ovan fast mer anonymt och institutionaliserat Walkthrough/inspection Gå igenom med några inspektörer, resulterar i ett åtgärdsprotokoll Inspection, den mer formella av de två, resultaten rapporteras vidare Statisk programanalys Formella bevis Översätt kod till logiknotation Bevisa från startvillkor att slutvillkoren kommer ske
Code review Olika typer: Över-axeln en utvecklare förklarar för en annan ansikte till ansikte Via e-post kommentarer förmedlas via e-post Parprogrammering två utvecklare skriver kod tillsammans Med hjälp av verktyg exempelvis kommentarer på en commit i GitLab
Walkthrough-/inspectionlista Felaktig användning av data Oinitierade variabler, arrayindex utanför gränser, dangling pointers Deklarationsfel Användning av icke-deklarerade storheter, dubbel deklaration i ett block Beräkningsfel Division-by-zero, overflow, typmismatchningar, operatorprioriteter Logikfel < istället för <=, and-or, operatorprioriteter Fel i styrning Oändliga loopar, varvräknarfel Interfacefel Antalet, typerna på parametrar, globala data
Formell verifikation - exempel i n t ack ( i n t m, i n t n ) { i f (m == 0) { r e t u r n n + 1 ; } e l s e i f ( n == 0) { r e t u r n ack (m 1, 1 ) ; } e l s e { r e t u r n ack (m 1, ack (m, n 1 ) ) ; } } Terminerar ack(m, n) för alla m, n 0?
Formell verifikation - exempel i n t ack ( i n t m, i n t n ) { i f (m == 0) { r e t u r n n + 1 ; // T e r m i n e r a r } e l s e i f ( n == 0) { r e t u r n ack (m 1, 1 ) ; // m minskar > t e r m i n e r a r! } e l s e { r e t u r n ack (m 1, // m minskar > t e r m i n e r a r! ack (m, n 1 ) ) ; // n minskar > t e r m i n e r a r! } } Både m och n minskar, så alla anrop terminerar i sinom tid Testa: ack(3, 3), ack(4, 4)
Formell verifikation Kan bevisa korrekthet på liknande sätt Finns många verktyg, vissa kräver assistans: Z3 prover: http://githubcom/z3prover/z3/wiki Coq Proof Assistant: http://coqinriafr
Dynamisk testning Funktionell - Black box testning Titta ej på koden! Testar bara funktionalitet utifrån specifikationen Strukturell - White box testing Titta på koden! Testa de svåra delarna Logik i villkorssatser, if, for, while, etc Extremvärden Egentligen vill man täcka all kod, få hög coverage Hitta lämplig testdata Unit testing Identifiera och testa gränsövergångar!
Unit testing A unit test is an automated piece of code that invokes a unit of work in the system and then checks a single assumption about the behavior of that unit of work Ett Unit-test är: Automatiserbart Isolerat Konsekvent Läsbart Lättunderhållet Pålitligt // can i t add t h e numbers 1 and 1? TEST_CASE( " Test adder ", " [ math ] " ) { AdderImpl adder { } ; REQUIRE( adder add ( 1, 1) == 2 ) ; } C++ unittest ramverk: Catch, Google Test, QtTest, unit++, etc
Code coverage På hur många sätt kan man ta sig från början till slut? 4((N + (1 + N)) + 2)?
Integrationstestning Modul C Modul A Modul B Modul A och B enhetstestas var för sig Modul C integrationstestas
Regressionstestning Ändringar kan introducera nya buggar eller återintroducera gamla buggar Använd tidigare skrivna tester, se om de fortfarande passerar Unit tests?
Testning - exempel Specifikation: Ett program som läser in tre heltalsvärden från en rad De tre värdena tolkas som längderna på de tre sidorna i en triangel Programmet skriver ut ett meddelande som anger om triangeln är likbent, liksidig eller om alla tre sidor är olika Uppgift: Skriv ett antal testfall (dvs kategorier plus några specifika testdata per kategori) som du anser testar programmet på ett bra sätt
Testning - exempel #i n c l u d e <i o s t r e a m > u s i n g namespace s t d ; i n t main ( ) { i n t x, y, z ; c i n >> x >> y >> z ; } i f ( x == y && y == z ) { cout << " T r i a n g e l n ä r l i k s i d i g \ n" ; } e l s e i f ( x == y x == z y == z ) { cout << " T r i a n g e l n ä r l i k b e n t \ n" ; } e l s e { cout << " A l l a s i d o r i t r i a n g e l n ä r o l i k a \ n" ; } r e t u r n 0 ;
Testning - exempel > make testprogram > /testprogram 1 1 100 Triangeln är likbent > /testprogram 0 0 0 Triangeln är liksidig > /testprogram -1-1 -1 Triangeln är liksidig > /testprogram 30 30 30 Alla sidor i triangeln är olika > /testprogram Klas, Kalle och Lotta Triangeln är liksidig
Testning - exempel Självevaluering av testfall: 1 Har du testfall som representerar en giltig oliksidig triangel? Obs, fall som 1 2 3 eller 2 5 10 gör inte det, de är inte giltiga trianglar! 2 Har du testfall som representerar en giltig liksidig triangel? 3 Har du testfall som representerar en giltig likbent triangel? Obs, ett testfall som har 2 2 4 är inte en giltig triangel! 4 Har du testat alla permutationer av ovanstående fall? 5 Har du ett testfall där en sida är 0? 6 För varje testfall ovan, specifierade du (i förväg!) det förväntade resultatet?
Ekvivalensklasser Klass Liksidig? Beskrivning Exempel x y z x + y z Nej Inte en triangel 1 1 3 x + z y Nej Inte en triangel 1 4 1 y + z x Nej Inte en triangel 8 2 2 x = y Ja - 2 2 3 x = z Ja - 3 1 3 y = z Ja - 2 3 3 x + y < z Nej Giltig triangel 2 3 4 x + z < y Nej Giltig triangel 2 4 3 y + z < x Nej Giltig triangel 3 2 3
Systemtest Test av hela systemet Mot slutet av projektet I verklig miljö, med alla externa beroenden på plats Testar också dokumentation, ex vis installationsmanual
Acceptanstest Utförs av kund I syfte att verifiera kraven Inte lika djupgående som systemtest
Testning - minnespunkter Utarbeta och dokumentera tester, inklusive förväntat utfall, i förväg! Gör alltså inga tester i flykten! Vid buggar, skriv ett test för att påvisa buggen, och sedan bekräfta att den är borttagen med testet! Ett test kan aldrig bevisa frånvaron av fel - bara påvisa förekomsten! När ska man sluta testa?
Slutdokument Användarmanual Promosida Beskriver hur produkten används Ska inte behöva ha programvaran till hands Säljande websida Viktigaste funktionaliteten