fbpx

Ako pokryť testami neznámy kód pred refaktoringom?

Niekedy stojíme pred problémom, že potrebujeme pokryť testami neznámy kód pred refaktoringom. V tomto článku sa pozrieme na jeden z možných prístupov.

V mojej práci sme raz mali za úlohu zrefaktorovať skupinu mapperov, ktoré produkujú textové výstupy pre externý systém. Tri rôzne implementácie a každá bola trochu iná, lebo mapujú niektoré detaily inak, alebo z iného zdroja údajov. Cieľom bolo zjednotiť čo najviac v spoločnom predkovi; presunúť niektoré nastavenia do konfigurácie; a nakoniec sprehľadniť rozdiely medzi nimi.

Problém

Problém bol v tom, že nikto nevedel ako presne majú tie mappery fungovať vo všetkých prípadoch. Navyše len jedna implementácia bola dobre pokryté testami. Dve mali pokrytie len okolo 30-40 %. Ako zabezpečiť, že refaktoringom niečo nepokazíme? Samozrejme, treba dopísať chýbajúce testy. Ale ako, keď nevieme, čo to má presne robiť?

Riešenie

Najjednoduchšie a asi aj najúčinnejšie riešenie z pohľadu pomeru cena/výkon sú Gold Master testy. Princíp je jednoduchý:

  • sprav test, ktorý zachytí výstupné údaje pre daný vstup a zapíše ich do súboru
  • opakuj pre všetky kombinácie vstupov, aby sa dosiahlo primerané pokrytie testovaného kódu
  • zmeň tieto testy tak, aby sa očakávané výstupy načítali zo súboru a porovnali s aktuálnymi výsledkami

Týmto postupom sme dosiahli to, že bez dôkladného poznania všetkých implementačných detailov sme rýchlo zachytili očakávaný výstup. Tu sa samozrejme predpokladá, že ten výstup je správny. Takže táto technika je použiteľná najmä v prípade starého kódu, ktorý už bol overený v produkcii. V praxi to nie je veľké obmedzenie, pretože predpoklad, že kód nikto dobre nepozná platí zvyčajne pri starom produkčnom kóde.

A potom sme vďaka testom zažívali už len samé klady a pozitíva — testy nám počas refaktoringu zachytili niekoľko vnesených chýb, ktoré nebol problém opraviť.

Alternanívne riešenie

Alternatívou je to isté, ale všetky individuálne hodnoty podchytíme pomocou assert. Tu by malo byť zrejmé, že takýto prístup je veľmi zdĺhavý, lebo každý jeden assert bude potrebovať explicitne napísať, spustiť, zistiť aktuálnu hodnotu a zapísať ju od assertu. Takže v porovnaní s uložením celého textového výstupu do súboru na jeden krát je oveľa menej efektívny.

Nevýhody

Nevýhodou zostáva to, že ak produkčný kód obsahuje chybu, tak výstupný súbor bude nesprávny a testy budú očakávať tú istú chybu aj po refaktoringu. Toto sa nám v skutočnosti aj stalo — rôzne mappery mali inú implementáciu toho istého, pričom v jednom bola chyba. V druhom bola už dávnejšie opravená. Refaktoringom sa do predka dostala tá správna. A teda test pre pôvodne chybnú implementáciu začal po refaktoringu zlyhávať. Našťastie kolega zodpovedný za túto časť mappera vedel o čo ide, overil si svoje predpoklady a dodatočne zmenil gold master data chybného testu.

Ďalšou nevýhodou je, že takéto testy sa zle udržiavajú. Nové požiadavky na komponent vyžadujú manuálne zmeny uložených údajov a to nie je príjemná ani bezpečná robota. Lenže my sme tieto testy vytvorili aby nám umožnili rýchlu a lacnú kontrolu pri veľkom refaktoringu. Takže svoju funkciu už splnili a keďže ich vytvorenie nezabralo veľa času, tak sa aj rýchlo zaplatili. A ak raz začnú spôsobovať problémy, tak ich môžeme vymazať a nahradiť kvalitnejšími testami. Po refaktoringu sa naša znalosť komponentu zvýšila a testy by malo byť jednoduchšie vytvoriť.

Záver

Robiť veľký refaktoring bez dostatočného pokrytia testami je riziko. Bez ohľadu na to, či kód dobre poznáte, alebo nie. Gold Master test je technika, pomocou ktorej za určitých okolností vieme pomerne lacno vytvoriť testy s dostatočným pokrytím a tak umožniť jeho refaktoring.