Menjalankan kembali kelas lengkap dan bukan hanya @Test di TestNG

9

Saya telah menjelajahi stackoverflow selama beberapa hari, mencoba menemukan cara menjalankan kembali seluruh kelas tes, dan bukan hanya @Testlangkah. Banyak yang mengatakan bahwa ini tidak didukung oleh TestNG dan IRetryAnalyzer, sementara beberapa telah memposting solusi, itu tidak benar-benar berfungsi. Adakah yang bisa melakukannya? Dan hanya untuk memperjelas alasan untuk ini, untuk menghindari jawaban yang mengatakan bahwa tidak didukung dalam tujuan: TestNG adalah alat yang tidak hanya untuk pengembang. Arti yang juga digunakan dari penguji sw untuk pengujian e2e. Tes E2e dapat memiliki langkah-langkah yang bergantung pada masing-masing dari yang sebelumnya. Jadi ya itu sah untuk menjalankan kembali seluruh kelas tes, daripada sederhana @Test, yang mudah dapat dilakukan melalui IRetryAnalyzer.

Contoh dari apa yang ingin saya capai adalah:

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"));

}

}

Katakanlah itu testStep_2gagal, saya ingin menjalankan kembali class DemoTestdan bukan hanyatestStep_2

gandalf_the_cool
sumber
Bisakah Anda menunjukkan kepada kami solusi yang tidak berhasil?
AndiCover
Harap edit pertanyaan Anda, sertakan sampel, dan tunjukkan kepada kami apa harapan Anda. Itu akan sangat membantu orang lain memberi Anda jawaban yang memenuhi harapan Anda.
Krishnan Mahadevan
@AndiCover Tautan ke penyelesaian yang tidak berfungsi (atau pemecahan masalah yang menghancurkan logika testNG): stackoverflow.com/questions/25781098/... stackoverflow.com/questions/50241880/… stackoverflow.com/questions/53736621/…
gandalf_the_cool

Jawaban:

1

Oke, saya tahu Anda mungkin menginginkan beberapa properti mudah yang dapat Anda tentukan di @BeforeClass Anda atau sesuatu seperti itu, tetapi kami mungkin harus menunggu untuk diimplementasikan. Setidaknya aku juga tidak bisa menemukannya.

Berikut ini adalah jelek sekali tetapi saya pikir itu melakukan pekerjaan, setidaknya dalam skala kecil, dibiarkan untuk melihat bagaimana berperilaku dalam skenario yang lebih kompleks. Mungkin dengan lebih banyak waktu, ini bisa diperbaiki menjadi sesuatu yang lebih baik.

Oke, jadi saya membuat Kelas Tes yang serupa dengan Anda:

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.");
        }

    }


Saya memiliki Listenerkelas super hanya dalam kasus saya ingin memperluas ini ke kelas lain, tetapi Anda juga dapat mengatur pendengar di kelas tes Anda.

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


Tiga dari 4 metode di atas memiliki a RetryAnalyzer. Saya meninggalkan testStep_4tanpa itu untuk memastikan bahwa apa yang saya lakukan selanjutnya tidak mengacaukan sisa eksekusi. Said RetryAnalyzertidak akan benar-benar mencoba lagi (perhatikan bahwa metode kembali false), tetapi akan melakukan hal berikut:

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

}


Ini akan membuat eksekusi di dalam eksekusi Anda. Itu tidak akan mengacaukan laporan, dan segera setelah selesai, itu akan melanjutkan dengan eksekusi utama Anda. Tetapi itu akan "mencoba kembali" metode dalam grup itu.

Ya saya tahu, saya tahu. Ini berarti bahwa Anda akan menjalankan suite pengujian Anda selamanya dalam lingkaran yang abadi. Itu sebabnya RetryAnnotationTransformer. Di dalamnya, kami akan menghapus RetryAnalyzer dari eksekusi kedua tes tersebut:

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

}


Sekarang kita memiliki yang terakhir dari masalah kita. Rangkaian uji asli kami tidak tahu tentang eksekusi "coba lagi" di sana. Di sinilah ia menjadi sangat jelek. Kita perlu memberi tahu Reporter kita apa yang baru saja terjadi. Dan ini adalah bagian yang saya anjurkan agar Anda tingkatkan. Saya kekurangan waktu untuk melakukan sesuatu yang lebih baik, tetapi jika saya bisa, saya akan mengeditnya di beberapa titik.

Pertama, kita perlu tahu apakah eksekusi retryTestNG berhasil. Mungkin ada sejuta cara untuk melakukan ini dengan lebih baik, tetapi untuk sekarang ini berfungsi. Saya mengatur pendengar hanya untuk eksekusi ulang. Anda dapat melihatnya di TestRetryatas, dan terdiri dari yang berikut ini:

public class TestListenerRetry extends TestConfig implements ITestListener {

    (...)

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

}

Sekarang Pendengar dari suite utama, yang Anda lihat di atas di kelas super TestConfigakan melihat apakah itu terjadi dan jika berjalan dengan baik dan akan memperbarui laporan:

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

                }

            }

        }


    }

}

Laporan tersebut harus menunjukkan sekarang 3 tes lulus (karena mereka coba lagi) dan satu gagal karena itu bukan bagian dari 3 tes lainnya:

Laporan terakhir


Saya tahu itu bukan apa yang Anda cari, tetapi saya membantu ini melayani Anda sampai mereka menambahkan fungsionalitas ke TestNG.

Rodrigo Vaamonde
sumber
Ups .. Saya lupa menambahkan persyaratan di Listener utama untuk hanya memperbarui laporan akhir jika Retry suite terjadi dan berhasil. Ditambahkan sekarang.
Rodrigo Vaamonde