Codice scoperto a seguito di refactoring

Le attività di refactoring e di manutenzione possono inavvertitamente portare alla rimozione della copertura di una classe, ma conoscendo il problema e utilizzando opportunamente gli strumenti a disposizione è possibile arginare il problema.

Scenario

Si ipotizzi che durante una sessione di sviluppo con TDD si definisca una suite di test TestA che specifica il comportamento della classe A. TestA stimolerà quindi un oggetto di tipo A e la classe A sarà quindi coperta dai test. Per semplificare l’esempio immaginiamo pure che la copertura di A sia pari al 100%.

A class covered by ATest
A class covered by ATest

Aderendo al tradizionale workflow red / green / refactor, ci si accorge che come sia possibile rifattorizzare il codice estraendo una nuova classe X, mantenendo in A un riferimento ad X. A questo punto quindi X sarà coperta solo grazie al fatto che TestA invoca metodi di A che a loro volta delegano alcuni compiti a X, in funzione di collaboratore.
Proseguendo lo sviluppo, si immagini di aggiungere una nuova suite TestB che definisce il comportamento della nuova classe B, che a sua volta utilizza anch’essa un oggetto di tipo X. Se TestB è scritto in stile “mockista”, l’oggetto di tipo B delegherà presumibilmente ad un test double di X e non ad un oggetto concreto di tipo X. Le classi A, B e X, comunque, risultano ancora coperte.

X indirectly tested.
X indirectly tested

 

Problema

Durante l’attività di manutezione ci si rende conto che la classe A non serve più e quindi questa viene rimossa, insieme a TestA. Quello che accade è che a questo punto X non è più coperta da alcun test, creando quindi una possibile fonte di errori di regressione.

X scoperta a causa della rimozione del test indiretto
X scoperta a causa della rimozione del test indiretto

 

Risoluzione

Come è possibile risolvere o prevenire questo problema ?

Evitare la copertura indiretta

Una prima idea è che quando durante un refactoring si estrae una nuova classe si dovrebbe rifattorizzare anche il corrispondente codice di test in modo da estrarne la sezione che stimola la nuova classe.

Garantire sempre una copertura diretta
Garantire sempre una copertura diretta

Coverage per l’identificazione di classi scoperte

Un’altra possibilità è quella di utilizzare sistemi di misurazione della copertura, con i quali ci si potrebbe immediatamente accorgere dopo la rimozione di A che la copertura di X è allo 0% e quindi correre immediatamente ai ripari.

Riferimenti

http://martinfowler.com/articles/mocksArentStubs.html