Safety net tests?


För ett par dagar sedan höll jag en liten informell presentation på jobbet om en metod jag brukar luta mig mot när jag refaktorerar kod. Metoden beskrivs i boken Working Effectively With Legacy Code av Michael Feathers och kallas för The Legacy Code Change Algorithm. Den består av dessa fem enkla steg:

1. Identify change points.
2. Find test points.
3. Break dependencies.
4. Write tests.
5. Make changes and refactor.

Egentligen är väl tanken att algoritmen ska användas för att angripa legacykod utan att riskera land och rike, men om man för en stund bortser från ”make changes” i punkt 5 återstår ju faktiskt ”refactor”.

Nu vore det kanske på sin plats att definiera ”legacy code”. Menar man en stor hög med spagettikod från antiken? Eller betyder det helt enkelt att koden är dammig och bortglömd? Det finns säkert många definitioner där ute, men egentligen behöver vi bara bry oss om hur Feathers definierar begreppet för att förstå hans algoritm. Hans definition är som följer:

”Legacy code is simply code without tests.”

Plain, simple och kanske lite brutalt. Oavsett vad man tycker innebär definitionen alltså att koden kan ha författats igår – utan tester klassar Feathers den som legacy.

Tillbaka till min presentation (och poängen med detta inlägg). I en av mina slides hade jag ställt upp algoritmen för Test-Driven Development (TDD) jämte The Legacy Code Change Algorithm för att på så sätt kunna resonera om hur vi kan förhålla oss till tester som skrivs i respektive algoritm. Här tycker jag att det finns en intressant skillnad som hänger ihop med testernas syften.

I TDD ingår författandet av tester som en del i utvecklingen. Syftet med tester som skrivs här är att öka kvalitén på koden som skrivs och att via tester skapa en slags dokumentation över hur koden används. Om vi sedan tittar på The Legacy Code Change Algorithm syftar testerna istället till att skapa förutsättningar för att genomföra förändringar utan att ta sönder saker. Det betyder också att testerna i sig inte nödvändigtvis behöver vara en naturlig del av koden (som i fallet med TDD).

För mig blir det med ovanstående resonemang mycket enklare att motivera användandet av mocking frameworks såsom Mockito eller PowerMock när jag refaktorerar legacykod. Med sådana frameworks tillämpar man en slags White-box testing där testerna till stor del lutar sig mot hur implementationen ser ut. Helt vanligt refaktoreringsarbete kan då ta sönder sådana tester – trots att kodens beteende fortfarande mycket väl kan vara alldeles riktigt och rätt – eftersom implementationens utformning förändras.

Jobbigt, jobbigt.

Men i en galet komplex kodmassa kan ramverk som Mockito göra hela skillnaden för att få en ärlig chans att refaktorera på ett säkert sätt. Om testerna blir väldigt svårförvaltade kan jag tycka att de på sätt och vis har spelat ut sin roll och kan tas bort. Koden som refaktorerades när testerna skrevs bör i vilket fall vara i ett bättre tillstånd än tidigare, vilket också var det vi ville uppnå.

Kanske vore det läge för en ny benämning för tester som skrivs i detta syfte? Vad sägs om Safety net tests? 😉


Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *