TDD flow diagram

Intro

Wat is TDD

TDD, of voluit Test Driven Development, is een aanpak van ontwikkeling waarbij we vertrekken van het schrijven van tests

Alvorens we de code schrijven voor een bepaalde functionaliteit, bedenken we welk resultaat we precies verwachten bij het triggeren van een bepaalde actie en zetten we dit alvast klaar in een test. 

Een voorbeeld hiervan is een date mapper functionaliteit. Wanneer je bepaalde input aan de mapper doorgeeft, verwacht je dat die er in een ander formaat uitkomt. 

$mappedDate = DateMapper:AmericanDatetoDefaultDate('05/27/2005'); 

self::assertEquals('2005-05-27', $mappedDate); 

Wanneer we deze test laten lopen, zal deze uiteraard falen en dat is ook de bedoeling. 

De volgende stap is om een minimum aan code te schrijven om de test de doen slagen. Daarna voeren we de test opnieuw uit en dit proces herhalen we tot alle assertions succesvol zijn en er dus aan alle verwachtingen voldaan werd. Zodra de test succesvol gelopen heeft, kijken we na hoe we de code kunnen optimaliseren of vereenvoudigen. Is de test succesvol met een minimum aan code, dan schrijven we de volgende unit test uit. 

 

Dit continue proces kan als volgt weergegeven worden: 
 

Zoals in bovenstaande tekst en diagram aangegeven, werken we met unit tests. Het is bij TDD belangrijk om te vertrekken vanuit kleine geïsoleerde functionaliteiten die eenvoudig getest kunnen worden. In een later stadium kunnen er dan uiteraard ook integration tests toegevoegd worden. 

Waarom kiezen voor TDD?

Test driven coderen heeft verschillende voordelen, zowel op korte als op lange termijn.
We vermelden hieronder de belangrijkste:

  • Onderhoudbaarheid en schaalbaarheid
    • Minimum aan code om een bepaald resultaat te behalen
    • Hierdoor bestaat de code uit kleine stukken begrijpbare code
    • Dat maakt het dan weer makkelijker om uitbreidingen toe te voegen
  • Return on investment

    • Op langere termijn zal de development tijd in verhouding heel wat lager zijn dan op een project dat niet volgens TDD ontwikkeld is

    • Door de falende tests die meteen naar boven komen, is de kans dat er bugs in het systeem sluipen veel kleiner. Deze worden immers al vroeg tijdens het development proces opgemerkt

    • De impact van changes op bestaande functionaliteiten is direct zichtbaar aan de hand van falende tests. De developer dient dus niet manueel verschillende testflows te doorlopen om de impact van zijn/haar tests na te gaan, wat in bepaalde gevallen een zeer tijdrovende taak kan zijn.

  • Vertrouwen

    • Als de code van de applicatie bij toevoegingen of aanpassingen steeds volledig en automatisch getest wordt, kan je gerust zijn dat de goede werking van de applicatie gewaarborgd blijft. Zo kan je als developer nieuwe functionaliteiten steeds vol vertrouwen lanceren.

Hoe implementeren we TDD bij Codana?

Bij Codana maken we gebruik van Gitlab CI/CD. In de pipeline definiëren we verschillende “stages” waarin er onder meer wordt nagekeken of de code voldoet aan de laatste standaarden. Dit gebeurt aan de hand van tools als codesniffer, psalm, grumphp, … 

Daarnaast is het ook in deze pipeline dat we onze tests geautomatiseerd laten lopen bij elke merge request. Mergen is enkel mogelijk wanneer alle tests “groen” zijn en zo zijn we zeker dat alles netjes blijft werken, ongeacht de nieuwe features of changes. 

Voorbeeld van referentieresultaten in Excel

Concrete implementatie

Calculatie tools

Onze klant Librius heeft voor hun ledenplatform “Libra” nood aan een berekeningsfunctionaliteit. Concreet dienen ze op basis van bepaalde input, de vergoedingen te berekenen voor alle uitgeverijen die lid zijn bij hen. 

Deze berekeningen brengen heel wat complexiteit met zich mee en dus is het belangrijk dat deze goed getest zijn alvorens te implementeren in een volledige flow. Test driven ontwikkelen was dan ook de logische keuze. 

 

Alvorens je kan starten met het schrijven van de tests, moet je natuurlijk over referentieresultaten beschikken. In dit geval was de beste optie om tot dergelijke referentieresulaten te komen, het “vertalen” van de functionaliteit naar een Excel bestand. Aan de hand van de formules die de klant ons aangeleverd had en een beperkte dataset (gebaseerd op real life data), stelden we een transparante Excel op waarin elke stap van de berekening apart vermeld wordt. Waar mogelijk, voegden we ook controlegetallen toe, die we later ook zullen kunnen verifiëren in onze tests (bvb. komt het totale percentage steeds op 100% uit). 

Deze Excel file werd aan de klant bezorgd zodat zij alle stappen en resultaten kon nakijken om vervolgens finale goedkeuring te geven om de berekeningen op deze manier te implementeren.

And so the testing begins...

Met de Excel hebben we een goede leidraad om onze testen op te bouwen. Per stap ontwikkelen we een unit test volgens het principe dat eerder omschreven werd. 

We isoleren de functionaliteit, bepalen welke resultaten we willen bekomen, zorgen ervoor dat de test faalt en schrijven de nodige code om een werkende test te bekomen. 

Dit proces herhalen we tot alle unit tests succesvol zijn en alle tussenstappen correct berekend kunnen worden. 

Bij deze unit tests maken we gebruik van exact dezelfde data als bij de vooropgestelde Excel. Op die manier kunnen we één op één nakijken of de resultaten correct berekend worden. Dit doen we door zowel de verwachte subresultaten te controleren als de controlegetallen. Als beide correct zijn en overeenkomen met de Excel, zijn we zeker dat de achterliggende code alles juist berekent. 

 

Nadat alle unit tests voor een bepaalde berekening uitgewerkt werden, schrijven we een integration test die alle stappen na mekaar gaat uitvoeren zodat we kunnen nagaan of ook de gehele flow een juist eindresultaat oplevert. 

 

Waar ligt hier nu juist het voordeel van test driven te werken? Er zijn talloze voordelen, maar we lichten er twee extra toe: 

  • Zekerheid: aangezien het om complexe financiële berekeningen gaat, is het belangrijk om zeker te zijn van de juistheid van de resultaten. We willen zowel zelf volledig vertrouwen hebben in onze code als onze klant de garantie te kunnen geven van de juistheid van de resultaten. Specifiek in dit geval kunnen we zo ook kleine zaken als afrondingsfouten snel opsporen en corrigeren. 

  • Onderhoudbaarheid: indien er in de toekomst gevraagd wordt een bepaalde aanpassing te doen aan een specifieke stap, kunnen we door middel van de tests zeer snel zien of deze aanpassing misschien ook andere stappen beïnvloedt en wat daar de mogelijke impact van is. Op die manier kunnen we onze code bijsturen zodat we de rest van de werking niet beïnvloeden 

Voorbeeld flow chart

Import flows

Een andere belangrijke functionaliteit binnen de Libra tool is het titelbeheer en dan meer specifiek de titelimport. Titels kunnen op meerdere manieren geïmporteerd worden, hetzij manueel, hetzij automatisch, maar eender hoe ze het systeem binnenkomen, voor elke titel dienen er verschillende checks doorlopen te worden. Op basis daarvan worden er onder andere extra kenmerken op de titel toegevoegd. 

De flow die doorlopen moet worden is vrij complex en bevat verschillende checks die noodzakelijk zijn voor mogelijke edge cases. 

Om hier een zo compleet mogelijk overzicht van te krijgen, stellen we samen met de klant een flow chart op dat doorlopen zal worden voor elke titel.  

Wanneer deze flow chart (theoretisch) volledig uitgewerkt is, nemen we enkele reële voorbeelden en doorlopen we stapsgewijs de flow om na te gaan of elke titel juist afgehandeld zou worden. Waar nodig sturen we de flow chart bij. 

Nadat de flow chart op punt staat, gaan we aan de slag met het isoleren van bepaalde functionaliteiten, zoals bijvoorbeeld de "flaggers". Dit zijn kleine stukjes code die bepaalde controles gaan doen op doorgegeven waardes en op basis daarvan een true/false waarde terugsturen. 

Eerst schrijven we weer kleine unit tests waarin we de verwachte resultaten valideren. Daarna schrijven we de functionaliteit van de mapper en passen we deze aan totdat we een succesvolle test bekomen. Zoals eerder vermeld, bekijken we, nadat de test slaagt, ook of we de code kunnen optimaliseren en vereenvoudigen. 

Stapsgewijs kunnen we zo ook voor deze functionaliteit zorgen voor 100% test coverage.

Conclusie

Hoewel test driven ontwikkelen in het begin een tijdrovende uitdaging lijkt, merk je al snel de voordelen op korte en lange termijn. Zo zullen bugs al vroeg in het development proces naar boven komen en bestaat je implementatie uit kleinere leesbare stukken code die makkelijk te onderhouden zijn naar de toekomst toe. 

Komen er toch issues naar boven in de toekomst, dan is de oorzaak ervan makkelijk te isoleren en op te sporen via de tests.

Auteur: Sarah Jehin
PHP developer
Sarah Jehin

More insights

Cross-platform applicaties met React Native

Nog nooit was het ontwikkelen van native mobiele applicaties zo toegankelijk als vandaag. Bij Codana doen we dit door gebruik te maken het React Native, een open-source framework dat werd ontwikkeld door Meta.

Auteur: Jinse Camps
Architect | Analyst
Jinse Camps
dev

Laracon EU 2024

Een fantastisch leerrijke ervaring om met een hoop Laravel gepassioneerde mensen te inspireren! Iets wat niet gemist kan worden en heel veel voeling geeft met de community. Wat een top evenement! Wie zien we volgende edities? 😮

Auteur: Noah Gillard
PHP / Laravel Developer
Noah Gillard AI generated Face
laracon codana persoon

Een efficiënt datamanagementsysteem voor toerisme

Een TDMS of Tourist Data Management System, is simpelweg een platform dat data uit verschillende bronnen ophaalt, intern al dan niet automatisch verwerkt en deze gegevens terug aanbiedt aan externe platformen.

Auteur: Tom Van den Eynden
Web Architect | Coordinator
Tom Van den Eynden
laptop

Systemen voor gegevensbeheer in toerisme

In dit artikel verkennen we wat een TDMS is, waarom het essentieel is voor de toerisme-industrie, en hoe technologieën zoals Laravel en ElasticSearch het verschil kunnen maken. 

Auteur: Tom Van den Eynden
Web Architect | Coordinator
Tom Van den Eynden
tdms

Beveiliging van Laravel 101

In deze blogpost gaan we dieper in op een aantal veelvoorkomende Laravel beveiligingsfouten.

Auteur: Robbe Reygel
PHP developer
laravel

De OSLO-standaard: hoe gestandaardiseerde gegevensuitwisseling ons verder brengt

De OSLO-standaard is een term die je misschien wel eens hebt horen vallen in de context van gegevensuitwisseling en digitale transformatie, maar wat houdt het precies in en wat zijn de voordelen ervan?

Auteur: Benjamin Verhaegen
PHP Developer
benjamin_verhaegen
shaking_hands_black_white