Testen van gemaakte software is een vanzelfsprekendheid, maar wat is het gevolg van testen? Dat er fouten gemaakt worden bij software ontwikkeling staat vast. Het voorkomen van fouten scheelt kosten. Vooral als fouten laat ontdekt worden zijn de kosten voor het verwijderen enorm. Het aantal fouten en moment van optreden wordt vaak gemeten en daardoor voorspelbaar. Capers Jones heeft op dit gebied zelfs al benchmarkgegevens gepubliceerd, waarmee een bedrijf zich kan meten.
Softwaretests zijn niet afdoende, dus worden voor het voorkomen allerlei technieken aangewend zoals geautomatiseerd testen, design reviews en code reviews. Maar kijken we wel genoeg naar het effect van deze methoden?
Als software goed geschreven is, dan is testen op bugs en reviewen onzinnig. Het is alsof je testscripts uitvoert op een volledig getest systeem en overal netjes groene vinkjes mag plaatsen. Je bent een hoop tijd kwijt geweest voor het maken van goede testscripts en kunt die snel uitvoeren en allemaal op geslaagd zetten. We weten dat dit in de praktijk bijna nooit het geval is, maar soms (of ten dele) wel. Waarom soms wel en soms niet?
Goede ontwikkelaar is lui
Een gezegde onder ontwikkelaars is: ‘een goede ontwikkelaar is lui'. De kern hiervan is dat een ontwikkelaar zo min mogelijk tijd wil besteden om iets te doen. Als hij iets moet doen dat saai en herhalend is, zal hij eerder een programma schrijven dat diezelfde taak uitvoert, dan dat hij het saaie werk doet. Met het programma spaart hij dan gelijk tijd uit. De luie ontwikkelaar is hier dus iemand die op een snelle en slimme manier zijn werk doet.
Toch wordt lui zijn meestal als negatief ervaren. Zo zijn er ontwikkelaars die een hekel hebben aan het onderhouden van de code van een ander, en ontwikkelaars die niet houden van testen. Gelukkig kunnen we hier aparte testers voor inschakelen, hetgeen niet helemaal probleemloos is.
Vangnet
De testers vormen namelijk een vangnet voor de luie ontwikkelaar. De ontwikkelaar denkt al snel: 'dat gaat de tester toch nog testen', dus staakt zijn eigen testinspanning. Een andere reden die een luie ontwikkelaar zal aandragen is natuurlijk tijdsdruk. Het is te lastig, complex en tijdrovend om dit helemaal door te testen is dan een veel gehoord argument. Voor een tester is het echter net zoveel of vaak nog meer werk. De combinatie van luiheid en geen zin in testen leidt hier tot het doorschuiven van de testinspanning en daardoor ook tot late foutdetectie.
Deze luiheid en het doorschuiven kunnen een vast patroon worden. De ontwikkelaar denkt niet eens meer na of hij zelf moet testen, want daar zijn tenslotte anderen voor. Het is als het ware werkverschaffing van de ontwikkelaar aan de tester. In tijden van crisis is baanbehoud natuurlijk prettig, maar dit is toch een structureel probleem.
Met of zonder vangnet
Iedereen kent de circusacts, waarbij gebruik wordt gemaakt van vangnetten. De vraag is of een circusact vaker mislukt met of zonder vangnet. Indien er een vangnet wordt gebruikt zijn de gevolgen niet zo groot. Lichamelijk zal de acrobaat niets mankeren, en hij kan waarschijnlijk zijn act vervolgen als hij/zij niet teveel geestelijk in paniek is geraakt. Als er geen vangnet is, zijn de gevolgen desastreus en zal de acrobaat de act mogelijk nooit meer uit kunnen voeren. In de softwareontwikkeling zijn de gevolgen minder duidelijk, maar toch is het goed even deze metafoor voor ogen te houden.
De slagingskans van de act zonder vangnet zal namelijk hoger liggen omdat de acrobaat zich iedere keer goed zal concentreren voordat hij begint aan zijn act. Er staat immers veel op het spel. Een tussenvorm is niet zo gebruikelijk, maar kan natuurlijk wel. Een vangnet met flinke gaten erin. De acrobaat zal alleen aan de gaten denken, maar heeft bij het vallen misschien wel geluk. In dit geval zou de acrobaat dus eigenlijk niet moeten weten waar er wel en waar geen vangnet is om tot het hoogste slagingspercentage te komen.
Niet meer testen
Als we dat doortrekken naar software ontwikkeling dan moet je de ontwikkelaars de indruk geven dat er niet meer getest wordt. Je laat ze alleen de gaten in het vangnet zien. Op die manier voelen ze zich zelf verantwoordelijk voor de correcte werking in productie. Dit sluit ook prima aan bij een Agile benadering waarbij eigen verantwoordelijkheid en brede kennis van de teamleden belangrijk is.
Ik probeer de ontwikkelaars in mijn team altijd hun eigen kwaliteit te laten toetsen. Door veel aandacht te geven aan principes en testen van eigen code door middel van unit tests. Het daarna door een ander laten reviewen of testen van de software moet voor de ontwikkelaar geen vanzelfsprekendheid zijn. De gevolgen van een fout worden hierdoor groter, echter zullen er minder fouten worden gemaakt. Voor de zekerheid kunnen nog wel toevallige code reviews of tests worden uitgevoerd. Zo verbetert de kwaliteit van de ontwikkelde software voordat er getest wordt door een aparte tester. Maar echt niet meer laten testen door een aparte tester vind ik wel een erg groot risico.
Verwijzingen
Jones, C. (2008), Applied Software Measurement: Global Analysis of Productivity and Quality, Third Edition, McGraw-Hill.
Het is dus een kwestie van kwaliteitsbewustzijn en het handelen daarop.
Als ontwikkelaars keer op keer laten blijken dat ze ‘lui’ zijn en dus broddelwerk afleveren, is er maar één oplossing: dáár is de deur – vertrekt u maar.
Dat vereist een cultuuromslag: wellicht iets minder de nadruk leggen op planning, en iets meer op kwaliteit. Het moet je eer te na zijn om je werk terug gestuurd te krijgen.
Ja en nee. De strekking is inderdaad dat als je een vangnet ophangt dit vangnet luiheid in de hand werkt. Een ABS levert later remmende automobilisten op. Menselijk gedrag. Maar is een vangnet of ABS dan onzinnig? Nee. Want dood laten vallen of te pletter laten rijden is ook geen optie. Wel is de rol van een tester anders en moet ook anders; niet testen achteraf maar begeleiden en vragen vooraf! Beter een goede vraag vooraf (toetsend) dan 1000 testen achteraf. De rol van een tester in ‘agile’ is meer gericht op het voorkomen van fouten dan het klassieke testen op de gebouwde functionaliteit. Achteraf. Want dat is duurder en levert het ongewenste vangnet op. Feitelijk is het niets meer dan het stimuleren van kwaliteitsbesef binnen (maar ook buiten) het team. De beste manier van toetsen is nog altijd vragen of iedereen binnen het team met de zojuist gebouwde auto de weg op durft. Met de handen los van het stuur en dan hard op de rem trappen….. het liefst op een gladde ondergrond 🙂
Een tester vroeg betrekken is natuurlijk een goede zaak.
Daarnaast: zorg dat de ontwikkelaar tussen de oren krijgt dat hij alleen resultaten oplevert die productiewaardig zijn.
Dus niet opleveren om te laten testen, maar opleveren om in productie te nemen (en dan uiteraard nog wel de kwaliteit controleren).
“Als software goed geschreven is, dan is testen op bugs en reviewen onzinnig.”.
Voordat je kunt concluderen dat de software goed geschreven is moet je dat toetsen. Overigens kan software goed geschreven zijn, maar toch niet voldoen aan de wensen van de gebruiker. M.a.w.: het is belangrijk om ontwikkelaars en testers continu in de loop te houden. Overigens vind ik testen compleet doorgeslagen tegenwoordig, vroeger deed de ontwikkelaar zelf zijn testen en was de kwaliteitsbewustheid groter. Vaak zie ik testers die niet eens weten wat software echt is en die staan dan al gauw met de mond vol tanden bij een ontwikkelaar. Voor een gesmeerde machine geef ik dan ook vaak voorkeur aan voormalige ontwikkelaars die het testvak leuk vinden. Dat maakt ook de kloof tussen ontwikkelaars en testers kleiner.
Over welke tests wordt hier gesproken als er “test” staat? Unit tests? Integratie tests? Acceptatie tests? (vul andere tests hier aan).
De programmeur zou elke opgeleverde applicatie inclusief unit tests moeten opleveren, de persoon aan wie dit wordt overgedragen kijkt of de tests voldoende diepgang hebben (maar ook niet teveel). Een van de manieren waarop dit kan gebeuren is via tools als Emma (als men met Java werkt in elk geval); maar alleen als deze tools als hulpmiddel worden gebruikt, niet als enigste bewijs.
Diverse mensen hebben al terecht aangedragen dat niet de programmeur moet zeggen dat het goede programmatuur is, maar dit moet aantonen door geslaagde tests.
Kortom: het artikel gaat om diverse redenen mank.
Dit stuk gaat eigenlijk maar over één onderdeel van testen als ik het zo doorlees: Testen op de technische aspecten van de software en fouten in de code. Ik denk zelf dat de beste ’tester’ om deze fouten te ontdekken de ontwikkelaar zelf is. Ook omdat een gevonden probleem dan snel is opgelost, de programmeur kan zelf het snelste het probleem oplossen. Dit is veel effectiever dan een aparte tester neer te zetten. De gemiddelde tester is niet constant bezig met programmeren en kent de code niet zo goed (of helemaal niet).
Het is altijd goed dat de programmeur samen gaat zitten met een tester, die als het goed is de testtechnieken beheerst, waardoor de programmeur zijn eigen (automatische unit) testscripts nog beter kan maken.
De tester zelf kan zich vervolgens gaan richten op de vraag :”Wordt de goede software gebouwd?”. Dit is meer dan het vinden van fouten in code. Dit komt meer neer op het controleren of de software die gemaakt wordt wel aansluit op de processen van de business en de wensen van de gebruikers.
‘Fouten vinden in code’ is meer gericht op de details, op onderdelen en losse functionaliteiten: focussen op de technische kwaliteit. De ‘aparte tester’ zal meer het overkoepelende verhaal moeten bekijken (de-focussen). Sluit het aan op de werkelijkheid. Verder kan de ‘aparte tester’ gespecialiseerd zijn in performance testen, security, usability of anders.
Hierdoor scheidt je de werkzaamheden op het testvlak, twee of meer soorten van tests (proces of specialisatie in testsoorten), waarbij je ook geen dubbel werk doet.
Één keer iets testen is genoeg, dubbel testen maakt het inefficiënt. In plaats van het vangnet zo groot mogelijk te maken worden er meerdere vangnetten opgehangen op de plaatsen waar de grootste risico’s zitten voor de business en gebruikers.
Een eenvoudige oplossing die ik met succes heb toegepast is als volgt. Alle software wordt wel degelijk getest door een aparte tester. Als hij echter meer dan een of twee voor de hand liggende fouten ontdekt – d.w.z. fouten die door de ontwikkelaar zelf redelijkerwijs gevonden hadden moeten worden – dan stopt hij gewoon met testen. De module gaat terug naar de ontwikkelaar met de boodschap om deze keer een goede unit test te doen. Meestal werkt dat heel effectief, zonder de drastische oplossing van Simon toe te passen.
Overigens werkt hetzelfde aanpak prima met reviews van documenten: als de reviewer al in de eerste paar pagina’s een waslijst aan fouten ontdekt, dan keurt hij het document af zonder de rest te lezen.
Wat dat betreft vind ik het principe van één van de vliegtuigbouwers wel leuk (ik weet niet of het een broodje aap verhaal is overigens, maar dat doet in dit geval niet af aan het principe): bij de eerste testvlucht vliegen alle engineers mee.
Zeker weten dat ze ervoor zullen zorgen dat ze goede kwaliteit afleveren op deze manier!
En daarmee kom je dan ook op de opmerking van Michiel: kwaliteit moet tussen de oren zitten.
Maar om dan maar niet meer te testen gaat een paar bruggen te ver.
Ik kan er heilig van overtuigd zijn dat ik goede software heb gemaakt, en kan het wellicht nog bewijzen ook. Echter, als ik de spec anders geïnterpreteerd heb dan de auteur, kan het zo maar zijn dat mijn software iets anders doet dan bedoeld. Een test door een onafhankelijk tester kan (let wel: kan) dit afvangen.
Dito voor wat grotere complexe systemen, liefst ontwikkeld op verschillende fysieke lokaties en zo. Alle ontwikkelaars en/of teams zijn er van overtuigd dat ze iets goeds hebben gemaakt, aan alle kwaliteitseisen voldoend. Maar als we alles gaan integreren op systeemniveau werkt het vaak toch niet. Daar kom je liever achter bij het testen dan op het moment dat je bij de klant staat met je spullen.
Wat ook niet gaat helpen is dat je in een aantal sectoren bepaalde test-bewijslast zult moeten overleggen alvorens je het product op de markt mag zetten. Ik voorzie een praktisch probleempje hier als ik niet meer ga testen.
Tot slot weet ik niet met wat voor ontwikkelaars de auteur gewerkt heeft, maar “ontwikkelaars de indruk geven dat er niet meer getest gaat worden” komt op me over alsof je ze als een stel domme ganzen wil behandelen. Ik ga de ontwikkelaars vertellen dat er niet meer getest wordt, maar er komen wel defects binnen omdat iets niet werkt ???
De ontwikkelaars waar ik mee gewerkt heb tot op heden zullen daar in ieder geval niet in trappen.
Misschien dat de auteur een carrière als autocoureur kan overwegen, daar kun je met een stuk minder risico bochten afsnijden.
@PaVaKe: Ja, dat is een broodje aap. Arbotechnisch niet toegestaan en ook dom om gelijk alle engineers de lucht in te laten gaan… 😉
Iets serieuzer: Vaak weet de ontwikkelaar niet alle wensen en eisen, omdat er aan de voorkant van een traject geen betrokkenheid wordt geregeld door managers. Ik ga in principe uit van de goede bedoelingen en vraag mij dan ook af wat exact de oorzaak of reden kan zijn van bevindingen op software. Als je die reden/oorzaak vindt, dan heb je al het halve werk gedaan. Ik noem het veel voorkomende voorbeeld van de projectmanager die eigenhands de inhoud gaat bepalen, alleen maar omdat zijn project dan lekker vlot gaat….
Ik heb gemerkt dat het ontwikkelen van geautomatiseerde test vaak veel meer tijd en moeite kost dan er in de (deel)applicatie gestoken kan worden.
Tenminste een functionele test is aardig maar dat het spul werkt geloof ik zo ook wel, het gaat zich om al die vele uitzonderings situaties waar je om te beginnen al niet eens aan denkt.
Simpel voorbeeldje y = a/(b-c) dat een deling door 0 kan opleveren. Dat staat nergens gespecificeerd.
Zelf maak ik vrij vaak testroutines omdat ik nogal eens te maken heb met veranderingen in specificaties (op zich al weer een heel artikel waard).
Ik vind dit overigens best een aardig artikel, en de reacties lijken dat ook wel te bevestigen.
@PaVaKe ik vloog ooit een kist waar net een nieuwe motor in was gezet die pas een half uurtje had proefgedraaid, gewoon zelf goed controleren voor je vertrekt.