TestNG'de sadece @Test'i değil, tüm sınıfı yeniden çalıştırın


9

Birkaç gün boyunca stackoverflow'a göz atıyorum, sadece bir @Testadım değil, tüm test sınıfını nasıl yeniden çalıştıracağımı bulmaya çalışıyorum . Birçoğu bunun TestNG ile desteklenmediğini ve IRetryAnalyzerbazılarının geçici çözümler gönderdiğini, bunun gerçekten işe yaramadığını söylüyor. Bunu başarabilen var mı? Ve sadece bunun nedenlerini açıklığa kavuşturmak için, bunun desteklenmediğini söyleyen cevaplardan kaçınmak için: TestNG sadece geliştiriciler için bir araçtır. Yani e2e testi için sw test cihazlarından da kullanılır. E2e testlerinin her biri öncekinden farklı adımlar olabilir. Yani evet, basit olarak değil, tüm test sınıfını yeniden çalıştırmak için geçerlidir @Test, ki bu kolayca yapılabilir IRetryAnalyzer.

Neyi başarmak istediğime bir örnek:

public class DemoTest extends TestBase {

@Test(alwaysRun = true, description = "Do this")
public void testStep_1() {
    driver.navigate().to("http://www.stackoverflow.com");
    Assert.assertEquals(driver.getCurrentUrl().contains("stackoverflow)"));

}

@Test(alwaysRun = true, dependsOnMethods = "testStep_1", description = "Do that")
public void testStep_2() {
    driver.press("button");
    Assert.assertEquals(true, driver.elementIsVisible("button"));

}

@Test(alwaysRun = true, dependsOnMethods = "testStep_2", description = "Do something else")
public void testStep_3() {
   driver.press("button2");
Assert.assertEquals(true, driver.elementIsVisible("button"));

}

}

Diyelim ki testStep_2başarısız oluyor, class DemoTestsadece tekrar değiltestStep_2


Bize çalışmayan geçici çözümü gösterebilir misiniz?
AndiCover

Lütfen sorunuzu düzenleyin, bir örnek ekleyin ve beklentilerinizin ne olduğunu bize bildirin. Bu, başkalarının size beklentilerinizi karşılayan bir cevap vermesine yardımcı olmak için uzun bir yol kat edecektir.
Krishnan Mahadevan

@AndiCover Çalışmayan geçici çözümlere (veya testNG mantığını yok eden geçici çözümlere) bağlantılar: stackoverflow.com/questions/25781098/… stackoverflow.com/questions/50241880/… stackoverflow.com/questions/53736621/…
gandalf_the_cool

Yanıtlar:


1

Tamam, muhtemelen @BeforeClass'ınızda veya bunun gibi bir şeyde belirtebileceğiniz kolay bir özellik istediğinizi biliyorum, ancak bunun uygulanmasını beklememiz gerekebilir. En azından ben de bulamadım.

Aşağıdaki cehennem kadar çirkin ama bence bu işi yapıyor, en azından küçük bir ölçekte, daha karmaşık senaryolarda nasıl davrandığını görmek için bırakılıyor. Belki daha fazla zamanla, bu daha iyi bir şeye dönüştürülebilir.

Tamam, ben de sizinkine benzer bir Test Sınıfı oluşturdum:

public class RetryTest extends TestConfig {

    public class RetryTest extends TestConfig {

        Assertion assertion = new Assertion();

        @Test(  enabled = true,
                groups = { "retryTest" },
                retryAnalyzer = TestRetry.class,
                ignoreMissingDependencies = false)
        public void testStep_1() {
        }

        @Test(  enabled = true,
                groups = { "retryTest" },
                retryAnalyzer = TestRetry.class,
                dependsOnMethods = "testStep_1",
                ignoreMissingDependencies = false)
        public void testStep_2() {
            if (fail) assertion.fail("This will fail the first time and not the second.");
        }

        @Test(  enabled = true,
                groups = { "retryTest" },
                retryAnalyzer = TestRetry.class,
                dependsOnMethods = "testStep_2",
                ignoreMissingDependencies = false)
        public void testStep_3() {
        }

        @Test(  enabled = true)
        public void testStep_4() {
            assertion.fail("This should leave a failure in the end.");
        }

    }


Ben Listenersadece ben diğer sınıflara bu uzatmak istedikleri takdirde süper sınıfta ama siz de test sınıfında dinleyici ayarlayabilirsiniz.

@Listeners(TestListener.class)
public class TestConfig {
   protected static boolean retrySuccessful = false;
   protected static boolean fail = true;
}


Yukarıdaki 4 yöntemden üçü a RetryAnalyzer. Bundan sonra yaptığım testStep_4şeyin yürütmenin geri kalanıyla uğraşmadığından emin olmak için onsuz bıraktım . Said RetryAnalyzeraslında yeniden denemeyecektir (yöntemin döndüğünü unutmayın false), ancak aşağıdakileri yapacaktır:

public class TestRetry implements IRetryAnalyzer {

    public static TestNG retryTestNG = null;

    @Override
    public boolean retry(ITestResult result) {
        Class[] classes = {CreateBookingTest.class};

        TestNG retryTestNG = new TestNG();
        retryTestNG.setDefaultTestName("RETRY TEST");
        retryTestNG.setTestClasses(classes);
        retryTestNG.setGroups("retryTest");
        retryTestNG.addListener(new RetryAnnotationTransformer());
        retryTestNG.addListener(new TestListenerRetry());
        retryTestNG.run();

        return false;
    }

}


Bu, yürütmeniz içinde bir yürütme oluşturur. Raporla uğraşmayacak ve biter bitmez, ana uygulamanıza devam edecektir. Ancak o gruptaki yöntemleri "yeniden deneyecek".

Evet, biliyorum, biliyorum. Bu, test paketinizi sonsuza kadar sonsuz bir döngüde yürüteceğiniz anlamına gelir. Bu yüzden RetryAnnotationTransformer. İçinde, RetryAnalyzer'ı bu testlerin ikinci uygulamasından kaldıracağız:

public class RetryAnnotationTransformer extends TestConfig implements IAnnotationTransformer {

    @SuppressWarnings("rawtypes")
    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        fail = false; // This is just for debugging. Will make testStep_2 pass in the second run.
        annotation.setRetryAnalyzer(null);
    }

}


Şimdi son sorunumuz var. Orijinal test paketimiz oradaki "tekrar dene" uygulaması hakkında hiçbir şey bilmiyor. Burası gerçekten çirkinleşiyor. Muhabirimize ne olduğunu anlatmalıyız. Ve bu sizi geliştirmeye teşvik ettiğim kısım. Güzel bir şey yapmak için zamanım yok, ama yapabilirsem, bir noktada düzenleyeceğim.

İlk olarak, retryTestNG yürütmesinin başarılı olup olmadığını bilmemiz gerekir. Muhtemelen bunu daha iyi yapmanın bir milyon yolu var, ama şimdilik bu işe yarıyor. Sadece yeniden denemek için bir dinleyici ayarladım. TestRetryYukarıda görebilirsiniz ve aşağıdakilerden oluşur:

public class TestListenerRetry extends TestConfig implements ITestListener {

    (...)

    @Override
    public void onFinish(ITestContext context) {
        if (context.getFailedTests().size()==0 && context.getSkippedTests().size()==0) {
            successful = true;
        }
    }

}

Şimdi ana süitin Dinleyicisi, süper sınıfta yukarıda TestConfiggördüğünüz, çalışmanın olup olmadığını ve iyi gittiğini görecek ve raporu güncelleyecek:

public class TestListener extends TestConfig implements ITestListener , ISuiteListener {

    (...)

    @Override
    public void onFinish(ISuite suite) {

        if (TestRetry.retryTestNG != null) {

            for (ITestNGMethod iTestNGMethod : suite.getMethodsByGroups().get("retryTest")) {

                Collection<ISuiteResult> iSuiteResultList = suite.getResults().values();

                for (ISuiteResult iSuiteResult : iSuiteResultList) {

                    ITestContext iTestContext = iSuiteResult.getTestContext();
                    List<ITestResult> unsuccessfulMethods = new ArrayList<ITestResult>();

                    for (ITestResult iTestResult : iTestContext.getFailedTests().getAllResults()) {
                        if (iTestResult.getMethod().equals(iTestNGMethod)) {
                            iTestContext.getFailedTests().removeResult(iTestResult);
                            unsuccessfulMethods.add(iTestResult);
                        }
                    }

                    for (ITestResult iTestResult : iTestContext.getSkippedTests().getAllResults()) {
                        if (iTestResult.getMethod().equals(iTestNGMethod)) {
                            iTestContext.getSkippedTests().removeResult(iTestResult);
                            unsuccessfulMethods.add(iTestResult);
                        }
                    }

                    for (ITestResult iTestResult : unsuccessfulMethods) {
                        iTestResult.setStatus(1);
                        iTestContext.getPassedTests().addResult(iTestResult, iTestResult.getMethod());
                    }

                }

            }

        }


    }

}

Rapor şimdi 3 testin (tekrar denendikleri gibi) ve diğer 3 testin parçası olmadığı için başarısız olduğunu gösteren bir test göstermelidir:

Son rapor


Aradığın şey olmadığını biliyorum, ancak TestNG'ye işlevsellik katana kadar size hizmet etmesine yardımcı oluyorum.


Hata! Ana Dinleyiciye yalnızca son raporu güncellemek için Yeniden Deneme paketi gerçekleştiğinde ve başarılı olduğunda bir koşul eklemeyi unuttum. Şimdi eklendi.
Rodrigo Vaamonde
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.