Blog om agile metoder, udvikling og ledelse


ordbog, værktøjskassen, test, programmering

TDD — test-drevet udvikling

Morten Ulrik Sørensen | 21.03.2020

Et at de gode værktøjer i udviklerens værktøjskasse er TDD, eller test-drevet udvikling.

Idéen er, at man lader sine unit-tests drive udviklingen af koden på denne måde (tilgiv de mange detaljer og små skridt, men de bittesmå skridt er netop pointen — du er dog velkommen til at springe over, hvis det bliver for meget):

  1. Skriv en test ("Når jeg bowler 2 i første kast og 3 i andet kast får jeg 5 point for runden")
  2. Kør testen. Det går galt, for der er ingen kode endnu, compileren er sur.
  3. Skriv kode, så det compiler ("laver en funktion, der tager en talrække og returnerer 0")
  4. Kør testen. Det går galt ("for resultatet er 0, ikke 5")
  5. Skriv kode, så testen går godt ("så returner da bare 5")
  6. Kør testen — hu hej, grøn bar: testen er glad!
  7. Skriv en test mere ("Når jeg bowler 1 i første kast og 2 i andet kast får jeg 3 point for runden")
  8. Rød bar, testen fejler ("funtkionen returnerer 5, ikke 3")
  9. Skriv den simpleste kode, der får begge test til at være glade ("Returner summen af de første tal")
  10. Grøn bar, testene er glade
  11. Skriv en fejlende test ("Når jeg ikke har bowlet endnu har jeg 0 point"), rød bar.
  12. Skriv den simpleste kode, der får alle tests til at være glade ("Returner summen af inputtet")
  13. Skriv en fejlende test ("Når jeg får 10 i første kast er min runde slut. Scoren kan ikke beregnes endnu"). Rød bar.
  14. Skriv kode, der får testene til at køre ("Hm, ok, nu er det ikke nok at returnere et tal. Jeg returnerer ...")

Rød bar, grøn bar, rød bar, grøn bar...

Lyder det som spild af tid? Det er det ikke, i hvert fald ikke for mig.

Alternativer

  • ingen unit-test — men så får man ikke automatisk at vide, hvis senere rettelser ødelægger noget
  • skriv koden først, testen bagefter — men man risikerer at glemme det, eller at noget "vigtigere" kommer i vejen, dagen er slut — og så er vi tilbage til "ingen test". Og man oplever også ofte, at koden ikke er let at skrive test til, fordi den lige er lidt for "sammenfiltret"

Fordele ved TDD

  • Man får hurtig feedback på sine beslutninger — samme sekund.
  • Man får tidligt tænkt over hvordan koden skal bruges — det hjælper mod et godt design.
  • Koden er automatisk "testvenlig".
  • Koden er naturligt brudt ned i små, testbare dele.
  • Man har helt sikkert husket at få skrevet test, og når man har god test-dækning tør man også trygt rette i og refaktorere koden.
  • Testene kan fungere som dokumentation til andre udviklere (og en selv om et par uger, når man ikke længere kan huske hvad man tænkte): hvordan skal dette modul bruges, hvad forventer den af input, og hvordan hænger output og input sammen?
  • Når nogen — måske mig selv — skal arbejde videre med koden en anden gang, så kan testene hjælpe mig i gang. Hvad sker der, hvis jeg retter her? Ah, så fejler den test. Hvad så hvis...
  • Hvis man slutter arbejdsdagen med en rød bar, så er det utroligt let at komme tilbage og komme i gang næste dag.
  • Rytmen (rød, grøn, rød, grøn, ...) hjælper mig med at komme "i zonen" og blive opslugt.
  • En stor og måske uoverskuelig opgave bliver brudt ned i en masse små, overskuelige skridt. (I mit bowling-eksempel kan jeg måske ikke lige gennemskue den rigtige algoritme i første hug — men jeg kan godt håndtere lige det næste eksempel også. Og så det næste.)
  • Der er masser af små lette skridt at tage fat på, hvis motivationen ikke er helt oppe, hvor man kan tackle de tunge problemer — og masser af små successer til at sparke motivationen i vejret.

Hvis du har arbejdet med test-drevet udvikling og holder af det, så ser du sikkert også andre fordele — lad mig gerne høre, hvad der er de største fordele for dig — og hvad der nogle gange afholder dig fra at lave TDD.