Casi di test approfonditi Looping - Una buona pratica?

1

A volte abbiamo un codice come questo:

private static final List<Goat> INEDIBLE_GOATS = [GOAT_A, GOAT_B, GOAT_C] 

void eatGoat(Goat goat) {
   if(INEDIBLE_GOATS.contains(goat)) {
       throw new CantEatGoatException();
   }
   ...
}

Dovrebbe essere testato al meglio (insieme a qualsiasi test per il consumo effettivo) come:

for(Goat goat: INEDIBLE_GOATS) {
   // forgive abuse of syntax
   assertThrows(CantEatGoatException, eatGoat(goat));
}

O più simile?

assertThrows(CantEatGoatException, eatGoat(GOAT_A));

I test dovrebbero verificare ogni tipo di capra non commestibile? O dovrebbero testare una capra rappresentativa dalla lista e credere che funzioni per le altre capre?

    
posta Winston Ewert 13.05.2014 - 01:39
fonte

4 risposte

5

Una delle ragioni principali per fare test è costruire la tua fiducia nel tuo codice. È possibile dimostrare che il codice testato ha una funzionalità specifica perché i test dicono che lo fanno. La fiducia cresce dalla prova. La domanda è, scorrendo tutto il INEDIBLE_GOATS , ottieni più fiducia nel tuo codice? In entrambi i casi, con test sia positivi che negativi, si copre il codice rilevante. Con il ciclo, però, stai praticamente esercitando queste linee più e più volte. In sostanza, stai verificando che List<Goat>#contains() faccia ciò che dice. Guadagni qualcosa da quello? Se ritieni che un List funzioni come dovrebbe, allora no, non ottieni nulla di aggiuntivo. Se, d'altra parte, non sei sicuro che un List funzioni come dovrebbe, dovresti avere un test separato di List#contains() per darti quella sicurezza.

Devi anche bilanciare il numero di test con le prestazioni della tua suite di test. Ripassare tutto il INEDIBLE_GOATS può darti un po 'più di sicurezza, ma se ci sono, diciamo, 1,8 milioni di loro, e il test dura più di 30 secondi, questa minuscola sicurezza aggiuntiva supera il tempo perduto (e la conseguente perdita di produttività ).

Infine, anche se INEDIBLE_GOATS può avere solo un piccolo numero di elementi, teoricamente, il numero di% non commestibile Goat s potrebbe essere infinito. È impossibile testare ogni potenziale Goat . Mentre in questo esempio semplificato, si può dire che non ci sarà veramente un% infinito di% co_de, in generale, dobbiamo rendere conto di input infiniti e quasi infiniti possibili e accettare che non possiamo praticamente testare tutto . Dobbiamo anche renderci conto che questa è una buona cosa. Non tutti gli input sono uguali e provare a testare tutto non ci procurerebbe più fiducia. Sta ottimizzando i test di fiducia che li rendono pratici e redditizi.

    
risposta data 13.05.2014 - 06:37
fonte
0

Il secondo test mi sembra più accurato. Se metti una capra nella tua lista, ti aspetti che la capra sia una capra fannullone (cioè, ti aspetti di ottenere true dal tuo metodo).

    
risposta data 13.05.2014 - 01:45
fonte
0

Sembra che tu stia semplicemente spingendo la logica intorno. Che ne dici di:

assertTrue(FOOBARABLE_GOATS.contains(goat));
    
risposta data 13.05.2014 - 01:46
fonte
0

La tua domanda è importante. Per riformulare in modo più generico: dovresti testare tutti i possibili input o solo quelli selezionati? Come @cbojar indica, il primo è tipicamente (a) non pratico o (b) non utile.

La domanda diventa quindi come rendere l'elenco di tutti i possibili input di test in un insieme di input di test optimal . Per fare ciò, dividere l'insieme di tutti gli input possibili in gruppi in base ai risultati attesi. Qualsiasi input da un gruppo dovrebbe produrre risultati equivalenti (sebbene non identici). Tali gruppi sono chiamati classi di equivalenza . e questo processo di identificazione di tali classi è partizionamento di equivalenza .

Come semplice esempio, per testare una funzione radice quadrata che prende un input intero, un buon punto di partenza sarebbe queste classi di equivalenza:

 1   -- all positive integers
-1   -- all negative integers
 0   -- zero

Potresti perfezionare ulteriormente l'elenco:

 1   -- all positive integers that are not perfect squares
 4   -- all positive integers that are perfect squares
-1   -- all negative integers
 0   -- zero

E se sei un vero stickler, potresti aggiungere maxint e minint per il tuo tipo intero. Ma con ognuno di questi hai infinitamente meno casi di test rispetto all'insieme di tutti i possibili input :-) - un risparmio piuttosto buono!

(Per ulteriori informazioni, vedere la mia risposta a una domanda correlata, Cosa testare con i test delle unità? )

    
risposta data 13.05.2014 - 23:05
fonte

Leggi altre domande sui tag