【问题标题】:Can I Skip Junit Tests if other tests fail?如果其他测试失败,我可以跳过 Junit 测试吗?
【发布时间】:2014-10-22 18:48:03
【问题描述】:

我正在使用 Junit 通过 Seleniun WebDriver 运行测试。我正在尝试将我的测试分成功能区域以便更好地报告错误。我创建了测试来测试页面加载/将文档移动到其他工作流程。如果页面加载测试失败,或者工作流程移动失败,我想跳过后续的页面/工作流程测试。

如果测试 A 失败,我如何跳过班级中的其余测试或在班级 B 中运行测试?

注意: 我意识到我要问的是“UNIT TESTS 的“不好的做法*”。但是,我实际上将 Junit 用于 Integration 和/或 Automation 测试。(取决于您的定义。) 我已经找到@Suite.SuiteClasses@FixMethodOrder 来订购我的测试类和测试方法。我试图命令它们在逻辑上运行,首先测试页面加载,然后将页面的每个功能作为单独的测试。一些功能,将信息移动到其他页面,意味着其他类。我的 1 节课可能需要 1/2 多小时才能完成。如果 pre-req 测试失败,我想短路“依赖”测试,以便更快地得到我的结果/报告。

【问题讨论】:

  • 为什么测试 A 失败了?
  • 测试 A 可能会失败,因为文档没有正确移动到其他工作流程,或者不是我希望在页面上看到的所有元素都在那里。 (取决于测试)
  • JUnit 不会按照确定的顺序执行测试。因此,您将无法确保某个测试在另一个测试之前运行。
  • 你永远不应该。良好的做法是获得完整的通过(句号)。您应该按照所有测试在逻辑上相互遵循的顺序排列您的 JUnit 测试。

标签: java junit selenium-webdriver automated-tests


【解决方案1】:

通过在@Before 或@Test 方法中使用Junit's 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() 可能抛出的任何其他异常类型,例如空指针异常。将 AssumptionVoilationException catch 子句编辑为 Exception 将允许在任何异常上跳过 test2。如果您还想捕获 Error 或 Throwable,只需添加一个 catch 子句并像 AssertionError 一样放入 Assume.assumeTrue(false)。或者你可以直接抛出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);
        }
        ...
    }
}

【讨论】:

  • JUnit 通常会为每个测试创建一个新的测试包装类实例,所以我认为testOneThrown 应该是static
  • 我认为它也取决于 junit 版本;当我测试上面的代码时,我有一个控制台打印机来确保 test1 运行一次。因此,如果它确实运行了多次,我会看到。而且由于 junit 没有承诺它将如何运行测试用例,我相信他们确实按照您的观点进行了更改。
【解决方案2】:

我建议您切换到 TestNG。签出this

顺便说一句:当我过去使用 Java 时(大约一年前)我没有为 JUnit 找到这样的解决方案。

【讨论】:

    【解决方案3】:

    您可以尝试通过规则界面操作测试,这里有一个示例: http://www.codeaffine.com/2013/11/18/a-junit-rule-to-conditionally-ignore-tests/

    这可能是一个很好的起点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-19
      相关资源
      最近更新 更多