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?
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.
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.
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 ).
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.
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,
...
})
What's wrong with calling System.exit()
?
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With