2016-06-01 30 views
9

Supponiamo un metodo semplice che getta uno per una coppia di indici non valida (array 2d).Come testare tutte le combinazioni di parametri errati?

Come verifico l'eccezione generata per tutte le combinazioni di indici errati ?

(ovviamente questa prova non continuerà se una chiamata genera un'eccezione)

@Test(expected = Exception.class) 
public void validateIndices(){ 
    check(0,-1); 
    check(-1,0); 
    check(0,COLS + 1); 
    check(ROWS + 1, 0); 
} 

Esiste un modo comune per testare variazioni dei parametri di un metodo?

+0

Come la maggior parte tutorial di base di test di unità dicono: prova di una condizione per ogni metodo di prova. Quindi avete bisogno di almeno quattro per le vostre quattro chiamate 'check'. – Tom

+0

@Tom non sarebbe molto duplicato ripeterlo quattro volte? – jam

+0

* "non sarebbe molto duplicato ripeterlo quattro volte?" * E allora? Tocca a voi.O vuoi un metodo 'validateIndices' fallito e devi controllare manualmente quale di queste chiamate ha fallito, hai metodi dedicati come' testCheck_invalidSecondArgument', quindi vedrai esattamente quale fallire. – Tom

risposta

6

Nel tuo caso, vorrei Parameterized il mio test di unità per testare tutte le combinazioni con lo stesso test ulteriori informazioni here.

Nel tuo caso sarebbe simile a questa:

@RunWith(Parameterized.class) 
public class MyTest { 
    @Parameterized.Parameters 
    public static Collection<Object[]> data() { 
     return Arrays.asList(new Object[][] { 
      { 0, -1 }, { -1, 0 } 
     }); 
    } 

    @Parameterized.Parameter 
    public int row; 

    @Parameterized.Parameter(value = 1) 
    public int col; 

    @Test(expected = IndexOutOfBoundsException.class) 
    public void validateIndices(){ 
     check(row, col); 
    } 
} 
0

Beh, se gli indici sono entrambi Integer valori, poi un ciclo con un'istruzione try-catch è possibile:

for (int i = iBegin; i < iEnd; i++) { 
    for (int j = jBegin; j < jEnd; j++) { 
    try { check(i, j); } 
    catch (Exception e) { iList.add(i); jList.add(j); } 
    } 
} 

(iList e jList sono in questo caso un tipo di Collection; iBegin, jBegin, iEnd e jEnd sono valori interi, che danno i limiti della variazione)

2

Th Le altre risposte sono ovviamente corrette, nel senso che fanno ciò che state cercando, ma hanno un grande aspetto negativo: possono solo verificare le condizioni di errore ... che dovete specificare manualmente .

Significato: questo tipo di test dimostra solo che il "codice in prova" fa la cosa prevista per quei casi ben definiti.

Confrontalo con un modello di programmazione in cui diresti all'ambiente: "questo è il modo in cui mi aspetto che la mia funzione si comporti"; e poi quell'ambiente cerca di trovare input che ... su cui la tua funzione si interrompe.

Se ti sembra interessante, dovresti dare un'occhiata a QuickCheck. Anche se non proprio "nativo" di Java e sicuramente non "mainstream" al momento ... potrebbe valere la pena di provarlo.

6

Oltre alla risposta @Nicolas_Filotto, è anche possibile utilizzare Junit Theories. È più leggibile e, a differenza di Parameterized, eseguirà il test con tutte le possibili combinazioni di parametri.

@RunWith(Theories.class) 
public class MyTest { 
    @DataPoints("cols") 
    public static int[] rowValues(){ 
     return new int[]{0, -1, 1, 2}; 
    } 
    @DataPoints("rows") 
    public static int[] colValues(){ 
     return new int[]{0, -1, 4, 5}; 
    } 

    @Theory 
    public void upperBoundIsChecked(@FromDataPoints("cols") int col, 
            @FromDataPoints("rows") int row){ 
     assumeTrue(row >= ROWS || col >= COLS); 
     try { 
      check(col, row); 
      fail("Should have thrown IllegalArgumentException"); 
     } catch (IllegalArgumentException ignore){} 
    } 

    @Theory 
    public void lowerBoundIsChecked(@FromDataPoints("cols") int col, 
            @FromDataPoints("rows") int row){ 
     assumeTrue(row < 0 || col < 0); 
     try { 
      check(col, row); 
      fail("Should have thrown IllegalArgumentException"); 
     } catch (IllegalArgumentException ignore){} 
    } 

    @Theory 
    public void validIndicesNoException(@FromDataPoints("cols") int col, 
             @FromDataPoints("rows") int row){ 
     assumeTrue(row >= 0 && col >= 0 && row < ROWS && col < COLS); 
     try { 
      check(col, row); 
     } catch (Exception e){ 
      fail("Should not have thrown an exception: " + e.getMessage()); 
     } 
    } 

} 

Ogni teoria controlla tutte le possibili combinazioni di righe e colonne che corrispondono alle ipotesi della teoria.

Oppure, se l'elenco dei colli e delle righe sono gli stessi, si potrebbe fare ancora più semplice:

@RunWith(Theories.class) 
public class MyTest { 

    @DataPoints 
    public static int[] values(){ 
     return new int[]{0, -1}; 
    } 
    @Theory 
    public void validateIndices(int col, int row){ 
     check(col,row); 
    } 
} 
+2

Le teorie sono molto utili per testare comportamenti ampi su combinazioni di punti dati. Un beneficio non menzionato è che se la teoria fallisce, i risultati di junit mostreranno la combinazione specifica di valori che ha causato il fallimento della teoria. –