2012-04-05 15 views
14

Ho una suite di test JUnit nella forma:Arresto suite di JUnit se particolare test fallisce

@RunWith(Suite.class) 
@Suite.SuiteClasses({ xx.class, yy.cass }) 

public class AllTests { 

public static Test suite() { 
    TestSuite suite = new TestSuite(AllTests.class.getName()); 
    //$JUnit-BEGIN$ 

    //$JUnit-END$ 
    return suite; 
} 
} 

Questo quindi chiama test di vaniglia come questo:

public class xxx { 

@Test 
public void test() throws { 
    ... 

Ho una situazione in cui mi piacerebbe piace fermare il resto della suite di test in esecuzione se c'è un errore o un errore nel primo test. Ma gli errori/errori negli altri sono ok e la suite dovrebbe completare il maggior numero di test possibile. Fondamentalmente, il primo test fallito indica che non è sicuro eseguire il resto.

È possibile?

risposta

6

Cosa c'è di sbagliato nel chiamare System.exit()?

+0

Come dovrei programmazione verificare se l'affermazione non è riuscito? – Jonathan

+0

Ok, vedo che potrei prendere AssertionError nel primo test e poi chiamare System.exit(), ma poi il test JUnit non passerà o fallirà, basta fermarsi. Sembra che ci dovrebbe essere un modo più elegante. – Jonathan

+5

Re: un modo più elegante, non credo che JUnit fornisca questa funzionalità fuori dalla scatola. Può portare all'accoppiamento tra i test. Idealmente i test dovrebbero essere indipendenti l'uno dall'altro e non essere influenzati da altri errori. Se insisti, allora il suggerimento di Hiro2k è il migliore. –

0

Stai facendo test utilizzando formica?

È possibile scrivere un listener di test personalizzato. Puoi impostarlo nel form http://ant.apache.org/manual/Tasks/junit.html (enableTestListenerEvents).

+0

Anche se questa è un'opzione, generalmente non utilizzo Ant (utilizzando Esegui come> JUnit Test in Eclipse). – Jonathan

+0

Come creeresti quel "listener di test personalizzato"? Ricevo la parte della formica con haltonfailure = "true", ma all'interno di una Suite non si ferma se uno dei test della Suite fallisce. Cosa è in grado di fare "listener di test personalizzato"? –

3

Se è il primo test, prendere in considerazione la possibilità di spostare la convalida su @BeforeClass e generare un'eccezione se non riesce. Quindi solo il metodo @AfterClass verrebbe eseguito in caso di questa eccezione.

Naturalmente, in questo modo ti mancano tutti gli artefatti di fixture creati nei metodi di configurazione di prova.

3

Sulla base della risposta di Hiro2k (grazie!) Ho utilizzato la seguente soluzione. È un po 'un trucco, ma funziona.

Il test che può impedire l'esecuzione di altri test si trova nella parte superiore dell'elenco @ Suite.SuiteClasses. Questo test ha quindi la seguente:

private static boolean shouldStopRestOfSuite = false; 

    @Test 
    public void test() throws Throwable { 
    try { 
      ... run some test code... 
    } 
    catch (Throwable e) { 
     shouldStopRestOfSuite = true; 
     throw e; 
    } 
} 

Nota È possibile che questo ha bisogno di prendere Throwable (non fa eccezione) in modo che cattura errori di asserzione. Inoltre, restituisce l'errore, quindi viene registrato da JUnit per l'analisi.

Poi c'è un altro metodo di prova:

@Test 
public void testKillIfNeeded() throws Exception { 
    if (!shouldStopRestOfSuite) { 
     return; 
    } 

    System.out.println ("Test suite killed due to dangerous error/failure"); 
    System.exit(1); 
} 

È possibile che questo è gestito secondo e ucciderà il processo di JUnit.

Utilizzando questo metodo, il test JUnit non si interromperà in caso di errore/errore in caso di problemi, ma l'errore/errore viene registrato per l'analisi da parte di JUnit e non verranno eseguiti ulteriori test.

Non troppo bella, ma non il lavoro :)

2

Come la tua risposta, ma utilizzando @Before in un test di integrazione, ho fatto qualcosa di simile:

public class FooTest { 

    private static boolean bar; 

    @BeforeClass 
    public static void setUpBeforeClass() throws Exception { 
     bar = false; 
    } 

    @Before 
    public void setUp() throws Exception { 
     assertTrue(bar); 
    } 

    @Test 
    public void test() { 
     System.out.println("something"); 
     assertTrue(true); 
    } 

    @Test 
    public void test1() { 
     System.out.println("Something2"); 
     assertTrue(true); 
    } 
} 

saluti!

10

Prima di tutto bisogna RunListener JUnit:

import org.junit.runner.notification.Failure; 
import org.junit.runner.notification.RunListener; 
import org.junit.runner.notification.RunNotifier; 

public class FailureListener extends RunListener { 

    private RunNotifier runNotifier; 

    public FailureListener(RunNotifier runNotifier) { 
     super(); 
     this.runNotifier=runNotifier; 
    } 

    @Override 
    public void testFailure(Failure failure) throws Exception { 
     super.testFailure(failure); 
     this.runNotifier.pleaseStop(); 
    } 
} 

quindi preparare una suite:

public class StopOnFailureSuite extends Suite { 

    public StopOnFailureSuite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError { 
     super(klass, suiteClasses); 
    } 

    public StopOnFailureSuite(Class<?> klass) throws InitializationError { 
     super(klass, klass.getAnnotation(SuiteClasses.class).value()); 
    } 

    @Override 
    public void run(RunNotifier runNotifier) { 
     runNotifier.addListener(new FailureListener(runNotifier)); 
     super.run(runNotifier); 
    } 
} 

ed eseguire la vostra suite:

@RunWith(StopOnFailureSuite.class) 
@Suite.SuiteClasses({ 
    FirstTestClass.class, 
    SecondTestClass.class, 
    ... 
}) 
+0

Per implementare la domanda, 'FailureListener' non dovrebbe interrompere il test in caso di errore. Potrebbe essere preferibile filtrare il tipo di errore e interrompere solo i test su un errore specifico. ad esempio, creando la tua classe 'Exception' e gettala nella tua' FirstTestClass'. Quindi utilizzare 'failure.getException()' per determinare se interrompere il test. – artificerpi

1

In primo luogo si dovrebbe prendere un errore e controllare la lo stesso prima di eseguire il secondo test.

@Rule 
public ErrorCollector collector = new ErrorCollector(); 

1. Aggiungi errore.

collector.addError(new Throwable("first thing went wrong")); 

2. Verificare prima della corsa dipendente.

collector.checkThat(getResult(), not(containsString("ERROR!"))); 

Riferimento - ErrorCollector