简体   繁体   English

如果测试失败,则重试 TestNG 代码中的特定代码段,而不是整个测试

[英]Retry a specific piece of code in a TestNG code if the test fails, not the whole test

I want to retry some method specific code if the TestNG test fails, and not retry the whole test.如果 TestNG 测试失败,我想重试一些特定于方法的代码,而不是重试整个测试。

I have looked into custom test Listeners and Retry analyzers from here https://github.com/haojiwu/testng-retry-example .我从这里查看了自定义测试监听器和重试分析器https://github.com/haojiwu/testng-retry-example This will rerun the whole test if it fails I want to some method specific code.如果它失败,这将重新运行整个测试我想要一些特定于方法的代码。

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

I want to do the code in doSomething(param1), the try the stuff in assertStuff(var1, var2) if the asserts in that fail I want to wait like 5 seconds and then retry the assertStuff(var1, var2) code if the asserts pass then the test pass, else retry up to 2 more times.我想在 doSomething(param1) 中执行代码,如果断言失败,则尝试 assertStuff(var1, var2) 中的东西我想等待 5 秒,然后重试 assertStuff(var1, var2) 代码如果断言通过然后测试通过,否则重试最多 2 次。

You probably want to use TestNG retryAnalyzer feature, but only for the assertStuff(var1, var2) part.您可能想使用TestNG retryAnalyzer功能,但仅适用于assertStuff(var1, var2)部分。

Therefore you should move the doSomething(param1) into a separate method, annotated with @BeforeClass (or @BeforeMethod ):因此,您应该将doSomething(param1)移动到一个单独的方法中,用@BeforeClass (或@BeforeMethod )注释:

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

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

    assertStuff(var1, var2);
}

Alternatively you can use @Test annotation for mandatory part and declare dependency between tests, eg:或者,您可以对强制部分使用@Test注释并声明测试之间的依赖关系,例如:

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

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

    assertStuff(var1, var2);
}

An easier way of getting this done without having to depend on RetryAnalyzer (one issue with RetryAnalyzer if you are not using the latest beta version viz., 7.0.0-beta5 or higher is that you would need to take responsibility of pruning the duplicate test results that result from the retrial).无需依赖 RetryAnalyzer 即可完成此操作的一种更简单方法(如果您不使用最新的 beta 版本,即7.0.0-beta5或更高版本,RetryAnalyzer 的一个问题是您需要负责修剪重复测试重审的结果)。

You could instead build a simple polling mechanism around your assertStuff() method and have it return true or false which you can assert.您可以改为围绕您的assertStuff()方法构建一个简单的轮询机制,并让它返回您可以断言的truefalse

Here's an example.这是一个例子。 For the sake of ease, I have leveraged using org.openqa.selenium.support.ui.FluentWait since its APIs are pretty concise为方便起见,我使用了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");
  }
}

In simple, we try like this also简单来说,我们也像这样尝试

    int iterate=5;
    boolean status=false;

    while(iterate >=1 && status ==false) {

        try {
            assertEquals("false", "true");
            status=true;
        }catch (AssertionError e) {
            iterate--;
            Thread.sleep(500);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM