【问题标题】:Retry a specific piece of code in a TestNG code if the test fails, not the whole test如果测试失败,重试 TestNG 代码中的特定代码,而不是整个测试
【发布时间】:2019-06-21 20:19:07
【问题描述】:

如果 TestNG 测试失败,我想重试一些特定于方法的代码,而不是重试整个测试。

我从这里https://github.com/haojiwu/testng-retry-example 研究了自定义测试侦听器和重试分析器。如果失败,这将重新运行整个测试我想要一些特定于方法的代码。

@Test()
public void testStuff() {
    String var1;
    String var2;

    /* Code specific to this test and should only be ran once. */
    doSomething(param1)

    /* Contains code looking for files that may or not be ready by the time the code is ran. */
    /* I want to try this code then wait and retry up to a max of 3 retries. */
    assertStuff(var1, var2);
}

我想执行 doSomething(param1) 中的代码,如果断言失败,则尝试 assertStuff(var1, var2) 中的内容我想等待 5 秒,然后重试 assertStuff(var1, var2) 代码如果断言通过则测试通过,否则重试最多 2 次。

【问题讨论】:

  • 欢迎来到stackoverflow。请添加您尝试过的代码并澄清您遇到的问题。更多信息here

标签: java testng


【解决方案1】:

您可能想使用TestNG retryAnalyzer 功能,但仅限于assertStuff(var1, var2) 部分。

因此,您应该将doSomething(param1) 移动到一个单独的方法中,并使用@BeforeClass(或@BeforeMethod)进行注释:

...
@BeforeClass
public void initSomething() {
    doSomething(param1);
}

@Test(retryAnalyzer = ThreeRetries.class)
public void testStuff() {
    String var1;
    String var2;

    assertStuff(var1, var2);
}

或者,您可以将@Test 注释用于强制部分并声明测试之间的依赖关系,例如:

...
@Test
public void initSomething() {
    doSomething(param1);
}

@Test(retryAnalyzer = ThreeRetries.class, dependsOnMethods = "initSomething")
public void testStuff() {
    String var1;
    String var2;

    assertStuff(var1, var2);
}

【讨论】:

    【解决方案2】:

    无需依赖 RetryAnalyzer 即可完成此任务的一种更简单的方法(如果您不使用最新的 beta 版本,即 7.0.0-beta5 或更高版本,RetryAnalyzer 的一个问题是您需要负责修剪重复的重试结果)。

    您可以改为围绕您的 assertStuff() 方法构建一个简单的轮询机制,并让它返回您可以断言的 truefalse

    这是一个例子。为了方便起见,我使用了org.openqa.selenium.support.ui.FluentWait,因为它的 API 非常简洁

    import java.time.Duration;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.function.Function;
    import java.util.function.Supplier;
    import org.openqa.selenium.TimeoutException;
    import org.openqa.selenium.support.ui.FluentWait;
    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    public class TestClass {
      private static final int max = 5;
    
      @Test
      public void testStuff() {
        doSomething();
        boolean wasAsserted = assertStuff(2);
        Assert.assertTrue(wasAsserted);
      }
    
      @Test
      public void testStuffThatFails() {
        doSomething();
        boolean wasAsserted = assertStuff(10);
        Assert.assertTrue(wasAsserted);
      }
    
      private boolean assertStuff(int retries) {
        final AtomicInteger integer = new AtomicInteger(0);
        Supplier<Integer> input = integer::getAndIncrement;
        FluentWait<Supplier<Integer>> checker =
            new FluentWait<>(input)
                .pollingEvery(Duration.ofSeconds(2))
                .withTimeout(Duration.ofSeconds(10));
        try {
          return checker.until(getCondition(retries));
        } catch (TimeoutException e) {
          return false;
        }
      }
    
      private Function<Supplier<Integer>, Boolean> getCondition(int retries) {
        return integerSupplier -> {
          int current = integerSupplier.get();
          return current == retries || current > max;
        };
      }
    
      private void doSomething() {
        System.err.println("I did something");
      }
    }
    

    【讨论】:

      【解决方案3】:

      简单来说,我们也这样尝试

          int iterate=5;
          boolean status=false;
      
          while(iterate >=1 && status ==false) {
      
              try {
                  assertEquals("false", "true");
                  status=true;
              }catch (AssertionError e) {
                  iterate--;
                  Thread.sleep(500);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2010-11-19
        • 2020-11-17
        • 2011-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-03
        • 2021-09-11
        • 1970-01-01
        相关资源
        最近更新 更多