che tipo di funzioni e / o classi sono impossibili da testare unitamente e perché

20

La scusa principale da parte dello sviluppatore per non avere un buon test unitario è "Il codice non è progettato in modo verificabile da unità". Sto cercando di capire quale tipo di design e codice non possono essere testati unitamente.

    
posta manizzzz 26.12.2013 - 21:58
fonte

6 risposte

27

Diversi fattori potrebbero rendere il codice difficile da testare. In questo caso, il refactoring aiuta a migliorare il codice affinché sia testabile.

Alcuni esempi di codice che sarebbe probabilmente difficile da testare:

  • Una funzione 1000-LOC,
  • Codice che si basa pesantemente sullo stato globale,
  • Codice che richiede concretezza, complica la creazione di oggetti, come il contesto del database, invece di affidarsi alle interfacce e all'iniezione delle dipendenze,
  • Codice che esegue lentamente ,
  • Codice degli spaghetti,
  • Codice legacy che è stato modificato per anni senza alcuna attenzione alla leggibilità o alla manutenibilità,
  • Difficile capire il codice che non ha commenti o suggerimenti sull'intenzione originale dell'autore (ad esempio il codice che utilizza nomi variabili come function pGetDp_U(int i, int i2, string sText) .

Si noti che la mancanza di un'architettura chiara non rende il codice difficile da testare unitamente, poiché i test unitari riguardano piccole parti del codice. Un'architettura poco chiara avrebbe comunque un impatto negativo sull'integrazione e sui test di sistema.

    
risposta data 26.12.2013 - 22:11
fonte
14

Ci sono molte cose che rendono il codice difficile da testare. Per coincidenza molti di questi capita anche di rendere il codice difficile da mantenere:

  • Law of Demeter violazioni.
  • Creazione di oggetti all'interno di un metodo anziché dipendenze per l'iniezione .
  • Accoppiamento stretto.
  • Scarsa coesione.
  • dipende strongmente dagli effetti collaterali.
  • Si basa pesantemente su globals o singleton.
  • Non espone molti risultati intermedi. (Una volta ho dovuto testare un'unità con una funzione matematica di dieci pagine con un singolo output e nessun risultato intermedio disponibile.I miei predecessori hanno praticamente codificato qualsiasi risposta che il codice ha dato).
  • Dipende pesantemente e direttamente dai servizi che sono difficili da prendere in giro, come i database.
  • L'ambiente di runtime è significativamente diverso dall'ambiente di sviluppo, come un target incorporato.
  • Le unità sono disponibili solo in forma compilata (come una DLL di terze parti).
risposta data 26.12.2013 - 22:24
fonte
5

Esempi comuni di persone con codice che non desiderano testare l'unità:

  • Codice che interagisce direttamente con i / o (lettura di file, chiamate di rete dirette, ...).
  • Codice che aggiorna direttamente l'interfaccia utente.
  • Codice che fa riferimento direttamente a singleton o oggetti globali.
  • Codice che modifica implicitamente lo stato dell'oggetto o del sotto-oggetto.

Usando un sistema di simulazione, tutti questi esempi possono essere testati su unità. È solo lavoro per impostare i sostituti simulati per le dipendenze interne.

Cose che davvero non possono essere testate da unità:

  • Cicli infiniti (per un gestore di thread, un driver o qualche altro tipo di codice a esecuzione prolungata)
  • Alcuni tipi di operazioni di assemblaggio diretto (supportate da alcune lingue)
  • Codice che richiede un accesso privilegiato (non impossibile, solo non una buona idea)
risposta data 26.12.2013 - 22:24
fonte
2

Ci sono alcune aree che possono rendere più difficile scrivere i test unitari. Tuttavia, sottolineo che ciò non significa che bisognerebbe scartare le tecniche utili semplicemente perché potrebbero aggiungere una certa complessità al test. Come con qualsiasi codifica tu dovresti fare la tua analisi per determinare se i benefici fuori i costi, e non accettare ciecamente ciò che alcuni ragazzi casuali inseriscono in rete.

Scritto male del codice progettato

  • accoppiamento inappropriato (solitamente accoppiamento stretto dove non dovrebbe essere)
  • codice sink (dove una funzione ha troppa logica / responsabilità)

Reliance of state in un ambito diverso

Il costo per la maggior parte di queste spirale fuori controllo a meno che tu non sappia cosa stai facendo. Sfortunatamente, molti spesso non sanno come usare queste tecniche per mitigare cose come la complessità dei test.

  • Singletons
  • Globali
  • Chiusure

Stato Esterno / Sistema

  • Dipendenze hardware / dispositivo
  • Dipendenze di rete
  • Dipendenze dal filesystem
  • Dipendenze tra processi
  • Altre dipendenze per le chiamate di sistema

Concorrenza

  • Threading (lock, sezioni critiche, ecc.)
  • fork'ing
  • coroutine
  • Call Backs
  • Gestori di segnale (non tutti, ma alcuni)
risposta data 29.12.2013 - 23:25
fonte
2

Non esiste un codice che non possa essere testato. Vi sono, tuttavia, alcuni esempi di codice che è VERAMENTE, VERAMENTE difficile da testare (al punto che probabilmente non ne vale la pena):

Interazioni hardware - Se il codice manipola direttamente l'hardware (ad esempio, scrivendo su un registro per spostare un dispositivo fisico), l'unità di test potrebbe essere troppo difficile o costoso. Se si utilizza l'hardware reale per il test, può essere costoso ottenere un feedback appropriato nell'imbracatura di test (ancora più attrezzatura!), E se non lo si fa, si deve emulare il comportamento esatto degli oggetti fisici - nessun piccolo trucco in alcuni esempi.

Interazioni orologio - Di solito è più semplice, perché è quasi sempre possibile prendere in giro le funzioni dell'orologio di sistema in modo piuttosto banale. Ma quando non ci riesci, allora questi test diventano ingestibili - i test basati su tempo reale tendono a richiedere molto tempo per essere eseguiti, e nella mia esperienza tendono a essere molto fragili mentre i carichi di sistema rendono le cose più lunghe di quanto dovrebbero , causando guasti al test fantasma.

    
risposta data 30.12.2013 - 04:18
fonte
0

I miei tre gruppi principali per questo sono:

  • codice che si basa su servizi esterni

  • sistemi che non consentono ai tester di modificare lo stato indipendentemente dall'applicazione.

  • ambienti di test che non replicano la configurazione di produzione.

Questo è quello che ho sperimentato di più quando uno sviluppatore è diventato ingegnere del QA.

    
risposta data 26.12.2013 - 22:25
fonte

Leggi altre domande sui tag