Sono necessari test unitari per una funzione che chiama solo un'altra funzione?

1

Assumendo OldModule.oldFunc , se vogliamo spostare oldFunc a NewModule e, per compatibilità con le versioni precedenti, mantenere oldFunc ci solo chiamando NewModule.newFunc passando gli stessi stessi argomenti e senza fare alcuna manomissione - do dobbiamo ancora scrivere test unitari per oldFunc ? Oppure i test unitari per newFunc sono sufficienti?

# Are unit tests still needed for oldFunc?
OldModule.oldFunc(args)
{
  return NewModule.newFunc(args)
}
    
posta Adelin 10.10.2018 - 08:28
fonte

3 risposte

6

Fortunatamente per te, dal momento che la funzione non sta facendo molto, sarebbe facile anche testarla. Alcuni secondi che utilizzerai per aggiungere un test unitario valgono una potenziale perdita di pochi minuti se qualcuno modifica inavvertitamente la funzione, o se la funzione si interrompe, influenzata da una modifica da qualche altra parte.

Come potrebbe una funzione così semplice interrompere?

Un esempio di regressione

Facciamo un esempio di un linguaggio tipizzato in modo dinamico. Sei nel mezzo di un refactoring per le ultime due settimane; alcune chiamate sono già state migrate a newFunc e solo pochissime sono ancora basate su oldFunc . Il nuovo codice è ben testato, ma oldFunc non ha affatto test.

Il tuo collega inizia a controllare un bug report. Sembra che sia correlato a un pezzo di codice ristretto in cui, tra gli altri, viene chiamato newFunc . Per correggere il bug, il tuo collega decide di aggiungere un argomento a newFunc : ora è newFunc(args, isSomething) e può essere chiamato specificando True o False per isSomething .

Il tuo collega esegue test unitari e, uno per uno, li corregge aggiungendo il parametro mancante ai chiamanti. La suite di test ora è completamente verde, quindi invia le modifiche alla produzione.

Alcuni minuti dopo, il telefono inizia a squillare ...

Poiché ti sei dimenticato di testare oldFunc , la modifica non è stata presa dalla suite di test. Il tuo collega ha introdotto una regressione perché il codice non è stato verificato . Semplicemente guardando il codice, il tuo collega non aveva idea di dover aggiornare oldFunc e tutti i chiamanti di oldFunc .

Che cosa testare?

Come puoi immaginare, non è necessario scrivere tutti i test unitari di newFunc per oldFunc : i test di oldFunc dovrebbero testare solo cosa sta facendo la funzione effettiva, non cosa qualche altra funzione chiamata è in esecuzione.

Questo significa che dovresti limitarti a un eventuale test.

Ulteriori modifiche

Se la vecchia funzione viene mantenuta solo temporaneamente, puoi - se la lingua ha un supporto per essa - decorare la funzione come obsoleta per fare in modo che il compilatore produca una serie di avvertimenti per ogni posizione nel codice che utilizza ancora la vecchia funzione . Il passo successivo potrebbe essere quello di sostituire la chiamata alla nuova funzione con un'eccezione, per catturare alcune posizioni in cui la funzione è stata chiamata, senza essere catturata dal compilatore; il test verrà quindi modificato di conseguenza per verificare che l'eccezione sia stata lanciata.

    
risposta data 10.10.2018 - 08:52
fonte
4

Se hai una funzione, dovresti fare dei test per questo. Questa raccomandazione varia in forza in base alla probabilità di difetti in una funzione . Ad esempio, i getter e i setter generati automaticamente con una sola riga si trovano proprio in fondo all'elenco delle priorità, mentre le funzioni critiche per l'azienda, lunghe e complicate, devono essere sottoposte a test da parte loro.

Che cosa significa questo per il tuo delegato legacy? È banale e quindi improbabile che abbia difetti; tuttavia, ha un lavoro da fare e dovresti testare che faccia questo lavoro. A seconda della natura della tua suite di test, potrebbe essere più semplice regolare una copia del test del test per la vecchia funzione, oppure puoi costruire una simulazione e verificare che oldFunc , infatti, chiami newFunc con stessi argomenti.

Ma non tralascerei i test solo perché l'attuale incarnazione di un punto di funzionalità è banale. Questo è un dettaglio di implementazione che potrebbe facilmente cambiare: dopo tutto, ha cambiato drasticamente proprio ora! E quando cambia, è improbabile che qualcuno si accorga che la decisione informale "non abbiamo bisogno di testare questo perché è banale" sarà ricordata e rivista. Quindi è meglio scrivere un semplice test e mantenere la copertura.

    
risposta data 10.10.2018 - 08:35
fonte
3

Are unit tests needed for a function that only calls another function?

Sì.

Assuming OldModule.oldFunc, if we want to move oldFunc to NewModule and, for backward compatibility, keep oldFunc there merely calling NewModule.newFunc by passing the exact same arguments and doing no tampering whatsoever -- do we need to still write unit tests for oldFunc?

Se oldFunc fa ancora parte dell'API pubblica supportata, è necessario eseguire test per verificare che il suo comportamento sia corretto. Il fatto che delega tutto il suo lavoro è un dettaglio di implementazione soggetto a refactoring.

La solita sequenza per rimuovere i test è:

  • Elimina la vecchia API e pianifica la sua rimozione
  • Attendi fino al termine del periodo di prova
  • Rimuovi i test
  • Rimuovi l'API

Se l'API non è stata pubblicata , hai molta più libertà nel distruggere le cose.

    
risposta data 10.10.2018 - 17:09
fonte

Leggi altre domande sui tag