java 如果特定测试失败,则停止JUnit套件

jei2mxaa  于 2023-02-11  发布在  Java
关注(0)|答案(8)|浏览(127)

我有一个JUnit测试套件,格式如下:

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

然后调用如下的普通测试:

public class xxx {

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

我遇到过这样的情况:如果第一个测试出现错误或失败,我想停止测试套件的其余部分运行。但是其他测试出现错误或失败是可以的,套件应该尽可能多地完成其他测试。基本上,第一个测试失败表明运行其余测试不安全。
这可能吗?

p8ekf7hl

p8ekf7hl1#

首先,您需要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();
    }
}

然后准备一个套件:

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

运行您的套件:

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

mzsu5hc02#

打电话给System.exit()有什么不对?

cgfeq70w

cgfeq70w3#

如果是first测试,则考虑将其验证移至@BeforeClass并在失败时抛出异常。如果出现此异常,则只有@AfterClass方法会运行。
当然,这样您就缺少了在测试设置方法中创建的所有fixture工件。

ssgvzors

ssgvzors4#

我喜欢你的答案,但是在集成测试中使用了@Before,我做了如下操作:

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

问候!

kg7wmglp

kg7wmglp5#

根据Hiro 2k的回答(谢谢!),我使用了下面的解决方案。这是一个有点黑客,但它的工作。
可以阻止其他测试运行的测试位于@Suite.SuiteClasses列表的顶部。该测试包含以下内容:

private static boolean shouldStopRestOfSuite = false;

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

注意,上面的代码确实需要捕获Throwable(而不是exception),这样它就可以捕获Assert错误,它还可以重新抛出错误,这样JUnit就可以记录错误以供分析。
还有一种测试方法:

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

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

上面的代码是第二次运行的,它将终止JUnit进程。
使用这种方法,如果出现问题,JUnit测试不会在失败/错误时结束,而是记录失败/错误以供JUnit分析,并且不会运行进一步的测试。
不是太漂亮,但它确实起到了作用:)

nafvub8i

nafvub8i6#

首先,您应该捕获一个错误,并在运行第二个测试之前进行检查。

@Rule
public ErrorCollector collector = new ErrorCollector();

1.添加错误。

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

2.在相关运行之前检查

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

参考-ErrorCollector

slmsl1lt

slmsl1lt7#

你在用ant做测试吗?
你可以编写一个自定义的测试监听器。你可以在ant http://ant.apache.org/manual/Tasks/junit.html(enableTestListenerEvents)中设置它。

x7rlezfr

x7rlezfr8#

我发现在这样一个成熟的库中实现这个功能太麻烦了,如果你使用JUnit 5 / Jupiter,你可以使用一个名为JUnit Pioneerhttps://junit-pioneer.org)的扩展。
使用JUnit Pioneer,您只需向测试类添加一个@DisableIfTestFails注解,就可以在一个测试失败时停止所有测试。

相关问题