IRetryAnalyzer выдает неверные результаты для тестовых случаев, определенных как SoftAssert - PullRequest
1 голос
/ 24 сентября 2019

У меня есть реализация Retry Logic для неудачных тестовых случаев с использованием IRetryAnalyzer, и в моих тестовых случаях определены 2 типа утверждений - Assert и SoftAssert.IRetryAnayzer работает нормально для обычного Assert, но не работает должным образом в случае SoftAssert.Ниже приведены подробные сведения сценария о возникшей проблеме:

  • Если тестовый пример, определенный как SoftAssert, завершается неудачно с первой попытки и проходит при следующей попытке, он продолжает повторяться до максимальной попытки повторной попытки, даже еслиТестовый пример проходит.В этом случае, если следующий контрольный пример, который определен как обычный assert (не-softassert), пройден, он также будет помечен как сбойный, даже если он проходит, и будет повторен для максимальной попытки повторной попытки.
  • Если все тестовые наборы определены как обычные утверждения, они работают как положено, т. Е. Если они терпят неудачу при первой попытке и проходят при следующей попытке, они продолжаются и не застревают в цикле повторных попыток.
  • Если тестовый пример определентак как SoftAssert проходит с первой попытки, он не повторяет попытку и переходит к следующим тестовым случаям, т.е. он работает, как и ожидалось.

Мне нужно сохранить несколько тестовых случаев как softAssert, так как я должен продолжить стестовый забег.Пример:

@Test(retryAnalyzer = RetryAnalyzer.class, groups = { "group1" }, priority=1)
    public void TestSection1(){
        Class1.verifyingAppLaunch(); //Defined as Assert
        Class1.Test1(); //Defined as softAssert
        Class1.Test2(); //Defined as softAssert
        Class1.Test3(); //Defined as softAssert
        Class1.Test4(); //Defined as softAssert
        Class1.Test5(); //Defined as softAssert
        softAssert.assertAll();
    }

Ниже приведен пример реализации IRetryAnalyer и ListenerAdapter.ListenerAdapter реализован для удаления дублирующихся тестовых случаев, которые были помечены как пропущенные как часть повторной реализации.В приведенном ниже примере кода, если samplecondition1 завершается с ошибкой в ​​первой попытке, он будет повторять попытку для максимального количества повторений, определенного, даже если он проходит во второй попытке, а также помечает samplecondition2 как сбой, даже если он проходит:

MyTestListenerAdapter.class

import java.util.Iterator;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;

public class MyTestListenerAdapter extends TestListenerAdapter {

    @Override
    public void onFinish(ITestContext context) {
        Iterator<ITestResult> skippedTestCases = context.getSkippedTests().getAllResults().iterator();
        while (skippedTestCases.hasNext()) {
            ITestResult skippedTestCase = skippedTestCases.next();
            ITestNGMethod method = skippedTestCase.getMethod();
            if (context.getSkippedTests().getResults(method).size() > 0) {
                System.out.println("Removing:" + skippedTestCase.getTestClass().toString());
                skippedTestCases.remove();
            }
        }
    }
}

TestRetryAnalyzer.class

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

public class TestRetryAnalyzer implements IRetryAnalyzer {
    int counter = 1;
    int retryMaxLimit = 3;

    public boolean retry(ITestResult result) {
        if (counter < retryMaxLimit) {
            counter++;
            return true;
        }
        return false;
    }
}

TestRetryTestCases.class

import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners(MyTestListenerAdapter.class)
public class TestRetryTestCases {
SoftAssert softAssert = new SoftAssert();

    @Test(retryAnalyzer = TestRetryAnalyzer.class)
    public void firstTestMethod() {
        System.out.println("First test method");
        if (samplecondition1 == true)
            softAssert.assertTrue(true);
        else
            softAssert.assertTrue(false);
softAssert.assertAll();
    }

    @Test(retryAnalyzer = TestRetryAnalyzer.class)
    public void secondTestMethod() {
        System.out.println("Second test method");
        if (samplecondition2 == true)
            Assert.assertTrue(true);
        else
            Assert.assertTrue(false);
    }
}

1 Ответ

2 голосов
/ 27 сентября 2019

Я не уверен, с какой версией TestNG вы работаете, но я не могу воспроизвести эту проблему, используя TestNG 7.0.0 (последняя выпущенная на сегодня версия).

У вас есть дополнительная проблемав вашем коде.Вы имеете SoftAssert в качестве глобальной переменной.SoftAssert по самой своей реализации запоминает все сбои.Таким образом, при каждой повторной попытке все ошибки сохраняются с первой попытки и до сих пор.Это означает, что метод @Test, включающий RetryAnalyser и использующий SoftAssert, в котором есть вероятность, что что-то не получится, приведет к тому, что этот метод тестирования никогда не пройдет.

При использовании SoftAssert выдолжен всегда объявлять и использовать объект SoftAssert в методе @Test, чтобы он создавался (и таким образом сбрасывался при каждой повторной попытке).

Вот тот же пример, который вы предоставили (я настроил его простонемного), который демонстрирует, что это прекрасно работает в 7.0.0

Как вы можете видеть из выходных данных, это только firstTestMethod (который имеет SoftAssert повторяется) и secondTestMethod (который имееттвердое утверждение и не провалилось) не повторяется.

тестовый класс (я только изменил это, все остальное заимствовано из вашего исходного поста)

import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;

@Listeners(MyTestListenerAdapter.class)
public class TestRetryTestCases {
  int softAssertCounter = 0;
  int hardAssertCounter = 0;

  @Test(retryAnalyzer = TestRetryAnalyzer.class)
  public void firstTestMethod() {
    SoftAssert softAssert = new SoftAssert();
    System.out.println("First test method");
    if (softAssertCounter++ > 2) {
      softAssert.assertTrue(true);
    } else {
      softAssert.assertTrue(false);
    }
    softAssert.assertAll();
  }

  @Test(retryAnalyzer = TestRetryAnalyzer.class)
  public void secondTestMethod() {
    System.out.println("Second test method");
    if (hardAssertCounter++ < 2) {
      Assert.assertTrue(true);
    } else {
      Assert.assertTrue(false);
    }
  }
}

** Повторный анализатор с некоторыми дополнительными регистрациями **

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

public class TestRetryAnalyzer implements IRetryAnalyzer {
  int counter = 1;
  int retryMaxLimit = 3;

  public boolean retry(ITestResult result) {
    if (counter < retryMaxLimit) {
      counter++;
      System.err.println("Retrying the test method " + result.getMethod().getMethodName());
      return true;
    }
    return false;
  }
}

Консольный вывод

First test method
Retrying the test method firstTestMethod
Retrying the test method firstTestMethod

Test ignored.

First test method


Test ignored.

First test method


java.lang.AssertionError: The following asserts failed:
    did not expect to find [true] but found [false]

    at org.testng.asserts.SoftAssert.assertAll(SoftAssert.java:47)
    at org.testng.asserts.SoftAssert.assertAll(SoftAssert.java:31)
    at com.rationaleemotions.stackoverflow.qn58072880.TestRetryTestCases.firstTestMethod(TestRetryTestCases.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133)
    at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:584)
    at org.testng.internal.TestInvoker.retryFailed(TestInvoker.java:204)
    at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:58)
    at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:804)
    at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:145)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.testng.TestRunner.privateRun(TestRunner.java:770)
    at org.testng.TestRunner.run(TestRunner.java:591)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:402)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:396)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:355)
    at org.testng.SuiteRunner.run(SuiteRunner.java:304)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1180)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1102)
    at org.testng.TestNG.runSuites(TestNG.java:1032)
    at org.testng.TestNG.run(TestNG.java:1000)
    at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:73)
    at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)


Second test method

Removing:[TestClass name=class com.rationaleemotions.stackoverflow.qn58072880.TestRetryTestCases]
Removing:[TestClass name=class com.rationaleemotions.stackoverflow.qn58072880.TestRetryTestCases]

===============================================
Default Suite
Total tests run: 2, Passes: 1, Failures: 1, Skips: 0
===============================================


Process finished with exit code 0
...