Voglio dividere un test di grandi dimensioni in test più piccoli in modo che quando superano i test più piccoli implicano anche il superamento del test di grandi dimensioni (quindi non c'è motivo di eseguire il test prova originale grande). Voglio farlo perché i test più piccoli di solito richiedono meno tempo, meno sforzo e sono meno fragili. Vorrei sapere se ci sono schemi di progettazione di test o strumenti di verifica che possono aiutarmi a ottenere questo risultato in modo robusto.Divisione di un test a una serie di test più piccoli
Temo che la connessione tra i test più piccoli e il test originale venga persa quando qualcuno cambia qualcosa nel set di test più piccoli. Un altro timore è che il set di test più piccoli non copre realmente il big test.
Un esempio di quello che sto puntando a:
//Class under test
class A {
public void setB(B b){ this.b = b; }
public Output process(Input i){
return b.process(doMyProcessing(i));
}
private InputFromA doMyProcessing(Input i){ .. }
..
}
//Another class under test
class B {
public Output process(InputFromA i){ .. }
..
}
//The Big Test
@Test
public void theBigTest(){
A systemUnderTest = createSystemUnderTest(); // <-- expect that this is expensive
Input i = createInput();
Output o = systemUnderTest.process(i); // <-- .. or expect that this is expensive
assertEquals(o, expectedOutput());
}
//The splitted tests
@PartlyDefines("theBigTest") // <-- so something like this should come from the tool..
@Test
public void smallerTest1(){
// this method is a bit too long but its just an example..
Input i = createInput();
InputFromA x = expectedInputFromA(); // this should be the same in both tests and it should be ensured somehow
Output expected = expectedOutput(); // this should be the same in both tests and it should be ensured somehow
B b = mock(B.class);
when(b.process(x)).thenReturn(expected);
A classUnderTest = createInstanceOfClassA();
classUnderTest.setB(b);
Output o = classUnderTest.process(i);
assertEquals(o, expected);
verify(b).process(x);
verifyNoMoreInteractions(b);
}
@PartlyDefines("theBigTest") // <-- so something like this should come from the tool..
@Test
public void smallerTest2(){
InputFromA x = expectedInputFromA(); // this should be the same in both tests and it should be ensured somehow
Output expected = expectedOutput(); // this should be the same in both tests and it should be ensured somehow
B classUnderTest = createInstanceOfClassB();
Output o = classUnderTest.process(x);
assertEquals(o, expected);
}
+1 Mantenere i test in una stessa classe (e la denominazione della classe di test come avete fatto) renderà meno probabile che qualcuno avrebbe accidentalmente freno il collegamento tra la prova originale e test più piccoli. Grazie per questo. Mi manca ancora un modo automatico per sapere che i test più piccoli implicano il superamento del test. – mkorpela
@mkorpela, puoi approfondire un po 'il motivo per cui è importante che i test più piccoli implichino il superamento del test? Se uno dei test più piccoli fallisce, non è sufficiente per indicare che esiste un problema? In ogni caso, la maggior parte dei corridori sperimentali presentano un'indicazione dello stato per l'intera classe di test. Ad esempio, i runner di test NUnit ed Eclipse JUnit contrassegnano la classe di test come "verdi" se tutti i test nella classe passano e "rossi" se un altro test fallisce. "TheBigTest" verrebbe contrassegnato come passante se tutti i test più piccoli passassero. –
@Hurme, non riesco a rimuovere il test originale se può fallire in una situazione in cui i test più piccoli potrebbero passare. – mkorpela