Wat werkt moet blijven werken: de kunst van het testen
In een vorige post werd de ontwikkelcyclus van een th!nx feature doorlopen. De concepten die daarin besproken werden maken echter deel uit van een groter geheel: geautomatiseerde tests van de volledige applicatie.
Bij het kiezen van het framework waarin th!nx geschreven zou worden, ondertussen al een aanzienlijke tijd terug, was het voor ons belangrijk onze klanten de zekerheid te geven dat nieuwe releases zo vlekkeloos mogelijk verlopen. Programmeurs zijn nog altijd mensen en mensen maken wel eens fouten. Dus stelden wij ons de vraag hoe we zoveel mogelijk bugs in de applicatie konden vermijden, maar er vooral ook voor zorgen dat bestaande code in de toekomst niet beïnvloed wordt (lees: niet meer werkt) door onze nieuwe code. Het framework waarin th!nx geschreven wordt heeft hiervoor mooie mogelijkheden en die worden dan ook consequent gebruikt.
In de programmeerwereld zijn een aantal testscenario’s courant. Men kan er zich vragen bij stellen waarom de volgende twee scenario’s nog altijd gebruikt worden, maar de realiteit is dat het wel degelijk nog gebeurt.
- De eindgebruiker is onze beste betatester
Programmeurs krijgen een bepaalde module toegewezen en gaan hier met veel ijver direct aan de slag met het implementeren van de effectieve code. Telkens wanneer zij een paar tientallen of honderden regels code geschreven hebben, openen zij hun browser en overlopen even het resultaat. Nu is het belangrijk te weten dat je als ontwikkelaar ook wel degelijk weet hoe je code in mekaar zit en bij het testen nog altijd de programmatie in het achterhoofd houdt. Het resultaat is dat wanneer het ding doet wat het moet, dat het ook als “klaar voor release” bestempeld wordt en de deur uitgaat.
Op dat moment wordt de klant eigenlijk de echte tester van de applicatie. De eindgebruiker zal altijd zaken doen die je als programmeur niet echt verwacht had en bij dat gefragmenteerde testen niet gecontroleerd hebt. Dat zorgt voor foutmeldingen of zaken die gewoon niet werken zoals ze horen, tot grote ontevredenheid van de eindgebruiker en bovendien een pak extra support die op zeer korte termijn moet aangepakt worden.
Uiteindelijk worden alle bugs wel uit de applicatie gevlooid, maar dit gaat ten koste van de klant en de persoon die support moet geven en het schept een slecht beeld van de applicatie. Daarom wordt in dit scenario meestal één klant als testcase gebruikt in de hoop van de meeste kemels eruit te krijgen voor de grote massa ermee te maken krijgt.
Dit is en blijft echter een manier van werken die niet houdbaar is. - Een interne testpersoon zal het wel vinden
In een poging om het aantal fouten voor de eindklant te beperken gaan we over tot één of meer personen intern die de nieuwe features gaan overlopen om te zien of ze naar behoren werken. Dit is zeker een stap vooruit. Alleen al het feit dat het niet dezelfde persoon is die de code geschreven heeft die zich bezighoudt met het testen zal een reeks fouten naar boven brengen die anders pas na de release opgemerkt zouden werken.
Er is echter nog steeds een factor waar geen rekening mee gehouden wordt in dit scenario: wat als de nieuwe code iets wat vroeger wel werkte opeens van gedrag verandert of erger, ervoor zorgt dat de correcte gegevens niet langer correct zijn.
Daarom wordt er dikwijls in dit scenario een checklist opgesteld van zaken die moeten gecontroleerd worden door de persoon die het programma overloopt. Die ligt met een lijstje naast zich en moet alles doorlopen en afpunten en ondertussen een nieuw lijstje opstellen voor de nieuwe feature.
Het mag dan ook duidelijk zijn dat op termijn heel wat pagina’s met testcases voor die persoon klaarliggen, terwijl er nog altijd veel kleine foutjes die heel diep in de applicatie verborgen zitten door de mazen van het net glippen.
Sowieso is het op lange termijn niet productief op deze manier te blijven werken en de motivatie van de personen die instaan voor de tests zal al snel onder het vriespunt zakken. Binnen een webapplicatie als thinx, die ondertussen al honderden features bevat en bovendien met financiële gegevens werkt, moet er gebruik gemaakt worden van iets dat met 100% zekerheid en geautomatiseerd gaat controleren of alles nog werkt. Dat is ook het geval en gebeurt veel efficiënter, maar vooral ook veel diepgaander dan een menselijke test kan.
In onze post over de ontwikkelingscyclus van th!nx waren we eigenlijk al onze tests aan het schrijven en gebeurt dit op twee niveau’s:
- Macro-niveau: de scenario’s beschrijven hoe de eindgebruiker door de applicatie zal stappen en wat de verwachtingen zijn
- Micro-niveau: elk klein stukje code van de modellen wordt getoetst of ze het gewenste resultaat opleveren, bijvoorbeeld: als de voornaam “Jan” is en de achternaam “Smet”, dan moet de volledige naam “Jan Smet” opleveren
Door deze ontwikkelcyclus weten we niet alleen dat onze nieuwe code zich gedraagt zoals wij het willen, maar door alle voorgaande testscenario’s zowel op macro als microniveau te laten overlopen kunnen we met grote zekerheid weten dat wat er al bestond zeker ook nog zal werken zoals we het vooropgesteld hadden. Ook bij het optimaliseren van code (zorgen dat deze sneller of beter verloopt) of het refactoren van bepaalde onderdelen (bestaande features in thinx uitbreiden of aanpassen) moeten we ons geen zorgen maken: ofwel zal de test nog altijd groen zijn, waardoor we weten dat alles nog werkt zoals voorheen, ofwel zal de test failen en dan weten we dat onze nieuwe code een fout bevat of dat de test zich niet van bepaalde nieuwe factoren bewust is. In beide gevallen kunnen we ingrijpen en de juiste beslissing nemen: ofwel de code aanpakken ofwel de test bijsturen.
Beelden zeggen nog altijd meer dan woorden, dus laten wij jullie graag ook zien waarom de kleur “groen” ons zo’n goed gevoel geeft:
Microniveau: RSpec model tests
In het filmpje (er werd wat tijd tussenuit geknipt) hieronder ziet u duidelijk hoe ondertussen al bijna 900 tests de revue passeren.
Macroniveau: Selenium integration tests
Deze tests worden uitgevoerd net zoals een echte persoon ze zou doen. Op deze manier kunnen we het principe van een testpersoon nabootsen, met dat verschil dat we dat gewoon op een aparte computer automatisch kunnen laten lopen en dat we bovendien in de scenario’s voor deze tests een mooie omschrijving van elke stap in het proces hebben.
Als voetnoot willen we toch nog even meegeven dat daadwerkelijk eens door th!nx lopen zeker nog behoort tot de eindfase voor een release, maar dat gebeurt met een grote zekerheid dat er niet veel naar boven zal komen. Als er nog iets onverwacht de kop opsteekt, dan wordt daar onmiddellijk een extra testje voor toegevoegd, dat ervoor zal zorgen dat dat randgeval ook weer in de toekomst gedekt zal zijn.