Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping JUnit suite if particular test fails

Tags:

java

junit

I have a JUnit test suite in the form:

@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;
}
}

This then calls vanilla tests like this:

public class xxx {

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

I have a situation where I'd like to stop the rest of the test suite running if there's an error or fail in the first test. But errors / fails in the others are ok and the suite should complete as many other tests as it can. Basically the first test failing would indicate it isn't safe to run the rest.

Is this possible?

like image 410
Jonathan Avatar asked Apr 05 '12 22:04

Jonathan


People also ask

How do I stop JUnit testing?

You press the 'Stop JUnit test run' wanting to halt the execution immediately. And it doesn't! Then you must go to the Debug view (why that name? i'm not debugging, i'm running) and 'Terminate' it from there.

How do you cancel test suite?

Currently there's no way to stop a test suite right away when a test case failed. However, in Test Suite UI there's an option to retry immediately which will retry the failed test case and stop the test suite if it keeps failing past the retry limit.

How do you stop Testng from running after a test fail?

If you want to do it from an arbitrary test, it doesn't appear there is a framework mechanism. But you could always flip a flag, and check that flag in the @BeforeTest setup method. Before you jump to that, maybe have a think if you could check once before the whole suite runs, and just abort there (ie @BeforeSuite ).

Is JUnit only report the first failure in a single test?

Why does JUnit only report the first failure in a single test? Reporting multiple failures in a single test is generally a sign that the test does too much and it is too big a unit test. JUnit is designed to work best with a number of small tests. It executes each test within a separate instance of the test class.


3 Answers

First you need junit RunListener:

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();
    }
}

Then prepare a 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);
    }
}

And run your suite:

@RunWith(StopOnFailureSuite.class)
@Suite.SuiteClasses({
    FirstTestClass.class,
    SecondTestClass.class,
    ...
})
like image 137
fab Avatar answered Oct 06 '22 16:10

fab


What's wrong with calling System.exit()?

like image 9
Hiro2k Avatar answered Oct 06 '22 16:10

Hiro2k


If it's first test then consider moving its validation to @BeforeClass and throw exception if it fails. Then only @AfterClass method would run in case of this exception.

Of course, that way you lack all the fixture artifacts created in test setup method(s).

like image 5
topchef Avatar answered Oct 06 '22 16:10

topchef