如果其他测试失败,我能跳过Junit测试吗?

3
我正在使用JunitSelenium WebDriver运行测试。我试图将我的测试分成功能区域以获得更好的错误报告。我创建了测试来测试页面加载/将文档移动到其他工作流程。如果页面加载测试失败或工作流程移动失败,我想跳过随后的页面/工作流程测试。
如果Test A失败,如何跳过类中其余的测试或运行Class B中的测试?
注意:我意识到我正在进行"单元测试"的"不良实践"。但是,我实际上正在使用Junit进行"集成"和/或"自动化"测试(取决于您的定义)。我已经找到了@Suite.SuiteClasses@FixMethodOrder来对我的测试类和测试方法进行排序。我试图按逻辑顺序运行它们,首先测试页面加载,然后将页面的每个功能作为单独的测试进行测试。其中一些功能会将信息移动到其他页面,也就是其他类。我的某个类可能需要半个小时才能完成。如果前置条件测试失败,我希望缩短"依赖"测试,以便更快地获得结果/报告。

为什么测试A失败? - dkatzel
测试A可能失败是因为文档没有正确移动到另一个工作流程中,或者页面上我期望看到的所有元素都不存在(取决于测试)。 - Raystorm
JUnit不按确定的顺序执行测试。因此,您将无法确保在另一个测试之前运行某个特定测试。 - Uwe Allner
你永远不应该。良好的实践是进行完整的测试(周期)。你应该按照逻辑顺序安排你的JUnit测试,使得所有测试都相互跟随。 - ha9u63a7
3个回答

3

通过在@Before或@Test方法中使用Junit的Assume,您可以使用以下任何一种方式跳过当前测试:

  1. 对于任何依赖于失败测试的测试,您可以使用Assume#assumeTrue(boolean)。 通过调用Assume.assumeTrue(false),您可以跳过当前测试。
  2. 对于可跳过的测试,请使用Assume#assumeNoException(Throwable),并在其他测试被跳过时传递AssumptionVoilated异常以跳过当前测试。

以下是一个例子:

public class Tests{
    @Test
    public void test1(){
        ...
    }

    @Test
    public void test2(){
        try{
            test1();
        }catch(AssertionError failExcep){
            //test1 failed, skip this test
            Assume.assumeTrue(false);
        }catch(AssumptionVoilationException skipExcep){
            //test1 was skipped, skip this test
            Assume.assumeNoException(skipExcep);
        }
        ...
    }
}

这个例子会运行test1()两次,但是通过添加@FixMethodOrder并在test1中捕获任何错误以便在test2中引用,我们可以规避这个问题。
此外,这个例子没有涵盖test1()可能抛出的任何其他异常类型,例如NullPointerException。将AssumptionVoilationException catch子句编辑为Exception将允许在任何异常情况下跳过test2。如果你还想catch Error或Throwable,只需添加一个catch子句并放入Assume.assumeTrue(false),如AssertionError。或者你也可以抛出AssumptionViolatedException
以下是简化版本。
@FixMethodOrder
public class Tests{

    private Optional<Throwable> testOneThrown;

    @Test
    public void test1(){
        try{
            ...
        }catch(Throwable t){
            // test1 throw something, catching it for test2() reference
            testOneThrown = Optional.of(t);
            /*
             * still throwing it for junit normal functions and
             * in case test2 ran independently
             */
            throw t;
        }
        //Ran successfully, making reference non-null but empty
        testOneThrown = Optional.empty();
    }

    @Test
    public void test2(){
        try{
            if(testOneThrown == null){
                // test1 did not run, thus needs to run
                test1();
            }else if(testOneThrown.isPresent()){
                // test1 ran and threw something
                throw testOneThrown.get();
            }
            //test1 ran and throw nothing
        }catch(Throwable thrown){
            /*
             * something was throw in test1, test1 could have
             * failed, could have been skipped, etc. thus skip 
             * this test.
             */
            throw new AssumptionViolatedException("Dependency on test1 failed.", thrown);
        }
        ...
    }
}

1
JUnit通常为每个测试创建测试包装器类的新实例,因此我认为testOneThrown应该是static - Adam Burley
我认为这也取决于junit的版本;因为当我测试上面的代码时,我有一个控制台打印机来确保test1只运行一次。所以如果它运行了多次,我会看到的。而且因为junit没有承诺如何运行测试用例,我相信他们已经按照你的观点进行了修改。 - Code Eyez

0
我建议你切换到 TestNG。看看这个this
顺便说一句:当我还在使用Java时——大约一年前——我没有找到JUnit的这样一个解决方案。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接