Lettura di un file prima di testare un metodo: è un test di integrazione o un test di unità?

2

Diciamo che scrivo un parser. Ci vuole un argomento che è un String e fa qualcosa con quello. Questo String può essere molto lungo, quindi tenerlo in una classe di test può sporcare il mio codice. Penso che sarebbe meglio mantenere questo String in un file e leggerlo durante il test unitario.

Ho dei dubbi se è ancora un test unitario o forse un test di integrazione. Penso che sia un test unitario perché continuo a testare solo il mio parser, non leggendo i dati dal file. Ma non riesco a trovare una fonte che possa confermare la mia ipotesi. Puoi dirmi che tipo di test è? Sarebbe anche bello provarlo con qualche risorsa o qualcosa del genere.

    
posta tdudzik 07.09.2016 - 12:10
fonte

3 risposte

3

Ciò che rende un test un'integrazione o un test di sistema è il fatto che il metodo in prova si basa su altre parti del sistema.

Immagina il seguente processo:

  • I dati vengono caricati dal database come enumerazione,
  • Un metodo percorre l'enumerazione e aggrega gli elementi in qualche modo,
  • Il risultato dell'aggregazione viene archiviato nel database.

Quando un'unità testa il metodo che aggrega gli elementi, non puoi semplicemente fare affidamento sulle chiamate al database: questo non sarebbe un test unitario perché ha dipendenze esterne; un errore nel codice del database fallirebbe il test, anche se il metodo stesso è corretto. In altre parole, non è possibile correlare il fallimento del test con l'errata impostazione del metodo:

  • Un test può iniziare a fallire anche se il metodo non è cambiato dall'ultimo passaggio.
  • Una regressione non può fallire il test perché è compensata da un cambiamento nella dipendenza esterna.

Quindi dovrai creare stub e mock per la logica di accesso ai dati, al fine di isolare il metodo. Si passa una determinata enumerazione al metodo e si controlla il risultato. Nessun database coinvolto.

Ora, dove ottieni i dati per l'enumerazione non ha molta importanza. Potrebbe venire dal codice. O dal database. O dal file flat. Questo fa parte del test , non del codice sotto test . Se il test chiama effettivamente un'API per ottenere gli elementi, è ancora un test unitario.

Tuttavia, i test unitari sono generalmente brevi e semplici, perché è più facile ragionarli quando sono brevi e semplici. Lo spostamento di dati in un file o in un database o in un'API rende il test [inutilmente] complicato. Ora, quando devi verificare il test dell'unità, devi cercare non in una, ma in due posizioni . Quindi mentre quelli sono ancora test unitari, possono diventare rapidamente un incubo di manutenzione. Il secondo problema è che un errore nell'origine dati esterna può portare a un test dell'unità fallito , in modo imprevisto.

  • L'uso di un file flat può essere OK (dopotutto, il codice sorgente non è altro che un file flat).

    Tuttavia, troverei strano che tu abbia bisogno di così tanti dati per il tuo test unitario che devi effettivamente metterlo in un file.

    Devi anche essere sicuro che i permessi del file system non interferiscano con i test delle unità e che il file non venga modificato per errore.

  • Usare un database sarebbe strano. Come si assicura che i dati siano corretti (se si inseriscono questi dati nella configurazione di test, non ha senso: si può passare direttamente al metodo testato, ignorando il database)? E i metodi che eseguono in parallelo?

    Inoltre, assicurarsi che il database sia installato correttamente e che funzioni non sia un compito facile. I test unitari probabilmente non hanno bisogno di tale complessità.

  • L'utilizzo di un'API è ancora più strano. Normalmente non controlli l'API, il che significa che potrebbe fallire in modo casuale, in mancanza dei test di unità senza motivo.

risposta data 07.09.2016 - 12:53
fonte
3

La mia opinione: se la stringa di input è così lunga che mantenere il metodo di test letterale sembra sporca, il test sta facendo troppo per un test unitario. Sta testando il parser su una parte lunga e complessa di dati del mondo reale. Va bene, ma di solito è il ruolo di un test di integrazione.

Mi aspetto che un test unitario provi una singola funzione del parser, o ogni funzione / percorso del codice / derivazione una volta . Se il punto è di testare il parser con una stringa di input lunga, è possibile creare dinamicamente una stringa lunga ripetendo un frammento adatto in un ciclo.

La domanda che si potrebbe porre è: se il parser non riesce su questo input lungo, potrebbe anche farlo fallire con un input più breve? Se sì, quindi trovare e utilizzare quell'input più corto di solito è una buona idea perché rende il test sia più breve che più veloce.

    
risposta data 07.09.2016 - 13:10
fonte
2

Quando si parla di test automatici, non esiste un ampio consenso in cui tracciare esattamente la linea tra test unitari e test di integrazione, nemmeno tra gli esperti. Sicuramente ci sono casi in cui la maggior parte degli esperti direbbe "questo è chiaramente un test unitario", e in altri casi dove la maggior parte delle persone direbbe "no, questo non è più un test unitario".

Ma nel tuo esempio, sono sicuro che troverai esperti che negheranno che testare un parser con una stringa di input enorme e complessa sia ancora un "test unitario", anche quando quella stringa è codificata direttamente nel codice sorgente del tuo test. Altri direbbero che "finché non devi fornire mock o stub al tuo parser, è un test unitario".

Quindi chiamalo test di unità, se preferisci, e un test di integrazione, se questo si adatta meglio alla terminologia del tuo ambiente.

    
risposta data 07.09.2016 - 13:16
fonte

Leggi altre domande sui tag