Cara membuat kelas tes dasar untuk tes Selenium dan menginisialisasi melalui JUnit RuleChain

Dengan artikel ini, kami melanjutkan serangkaian publikasi tentang bagaimana kami mengotomatiskan proses pengujian manual (selanjutnya disebut sebagai tes otomatis) dari sistem informasi besar (selanjutnya disebut sebagai Sistem) di salah satu proyek LANIT utama dan apa yang datang darinya.

Bagaimana cara mengatur hierarki kelas secara efisien? Bagaimana cara mendistribusikan paket pada pohon proyek? Bagaimana memastikan Anda lupa menggabungkan konflik dengan tim 10 orang? Masalah-masalah ini selalu pada awal perkembangan baru dan mereka tidak pernah punya cukup waktu.

Sumber

Dalam artikel ini, kami menggambarkan struktur kelas dan organisasi kode, yang memungkinkan kami untuk mengembangkan dengan sedikit usaha lebih dari satu setengah ribu tes UI end-2-end berdasarkan Junit dan Selenium untuk sistem besar signifikansi federal. Selain itu, kami berhasil mendukungnya dan terus memperbaiki skenario yang ada.

Di sini Anda dapat menemukan deskripsi praktis tentang struktur hierarki kelas dasar autotest, uraian proyek sesuai dengan model fungsional paket java dan contoh templat dari kelas nyata.

Artikel ini akan bermanfaat bagi semua pengembang yang mengembangkan tes mandiri berdasarkan Selenium.

Artikel ini adalah bagian dari publikasi umum di mana kami menggambarkan bagaimana sebuah tim kecil membangun proses otomasi pengujian UI dan mengembangkan kerangka kerja berdasarkan Junit dan Selenium untuk ini.

Bagian sebelumnya:


Implementasi kelas dasar untuk semua tes dan JUnit RuleChain


Konsep pengembangan autotest, seperti yang ditunjukkan pada artikel sebelumnya ( Bagian 2. Teknis. Arsitektur dan stack teknis. Detail implementasi dan kejutan teknis ), didasarkan pada gagasan tentang kerangka kerja di mana seperangkat fungsi sistem disediakan untuk semua autotest - mereka terintegrasi dengan mulus dan memungkinkan pengembang Autotests fokus pada isu-isu spesifik dari implementasi bisnis kelas uji

Kerangka kerja ini meliputi blok fungsional berikut:

  • Aturan - inisialisasi dan finalisasi komponen infrastruktur pengujian sebagai inisialisasi WebDriver dan menerima tes video. Dijelaskan lebih rinci di bawah ini;
  • WebDriverHandlers - fungsi tambahan untuk bekerja dengan driver web sebagai eksekusi Java Script atau akses ke log browser. Diimplementasikan sebagai satu set metode statis tanpa-negara;
  • WebElements adalah pustaka elemen web biasa atau grup mereka, yang berisi fungsionalitas lintas fungsi yang diperlukan dan perilaku tipikal. Dalam kasus kami, fungsionalitas ini mencakup kemungkinan pemeriksaan penyelesaian operasi asinkron di sisi browser web. Diimplementasikan sebagai ekstensi elemen web dari perpustakaan Selenium dan Selenide.

Inisialisasi lingkungan pengujian. Aturan


Kelas utama untuk semua kelas tes adalah BaseTest, dari mana semua kelas tes diwarisi. Kelas BaseTest mendefinisikan "runner" tes Junit dan RuleChain yang digunakan, seperti yang ditunjukkan di bawah ini. Akses dari kelas uji terapan ke fungsi yang disediakan oleh kelas aturan disediakan melalui metode statis kelas aturan.

Kode sampel BaseTest disajikan di kotak berikutnya.

@RunWith(FilterTestRunner.class) public class BaseTest { private TemporaryFolder downloadDirRule                                                                  = new TemporaryFolder(getSomething().getWorkingDir());      @Rule     public RuleChain rules = RuleChain             .outerRule(new Timeout(TimeoutEnum.GLOBAL_TEST_TIMEOUT.value(),                                                                       TimeUnit.SECONDS))             .around(new TestLogger())             .around(new StandStateChecker())             .around(new WaitForAngularCreator())             .around(downloadDirRule)             .around(new DownloaderCreator(downloadDirRule))             .around(new EnvironmentSaver())             .around(new SessionVideoHandler())             .around(new DriverCreator(downloadDirRule))             .around(new BrowserLogCatcher(downloadDirRule))             .around(new ScreenShooter())             .around(new AttachmentFileSaver())             .around(new FailClassifier())             .around(new PendingRequestsCatcher());     //            final protected SomeObject getSomething() {         return Something.getData();    }    … } 

FilterTestRunner.class - perpanjangan dari BlockJUnit4ClassRunner, menyediakan pemfilteran komposisi tes yang dapat dieksekusi berdasarkan ekspresi reguler dengan nilai anotasi Filter khusus (nilai = "some_string_and_tag"). Implementasinya diberikan di bawah ini.

org.junit.rules.Timeout - digunakan untuk membatasi kelanjutan maksimum tes. Ini harus diinstal terlebih dahulu, karena memulai tes di cabang baru.

TestLogger adalah kelas yang memungkinkan pengujian mencatat peristiwa dalam format json untuk digunakan dalam analitik ELK. Memperkaya acara dengan data uji dari org.junit.runner.Description. Selain itu juga secara otomatis menghasilkan acara untuk ELK dalam format json untuk memulai tes dengan durasi dan hasilnya

StandStateChecker adalah kelas yang memeriksa ketersediaan antarmuka web dari dudukan target SEBELUM menginisialisasi driver web. Memberikan pemeriksaan cepat bahwa dudukan tersedia pada prinsipnya.

WaitForAngularCreator - kelas yang menginisialisasi pengendali driver web untuk mengontrol penyelesaian operasi sudut asinkron. Ini digunakan untuk menyesuaikan tes "khusus" dengan panggilan sinkron yang panjang.

org.junit.rules.TentaraFolder - digunakan untuk mengatur folder sementara yang unik untuk menyimpan file untuk upload file dan mengunduh operasi melalui browser web.

DownloaderCreator adalah kelas yang menyediakan dukungan untuk operasi unggahan ke direktori sementara file yang diunduh oleh browser dan direkam melalui fungsi video Selenoid.

EnvironmentSaver - kelas yang menambahkan informasi umum tentang lingkungan pengujian ke laporan Allure.  

SessionVideoHandler - kelas yang mengunggah file uji video, jika ada, dan menerapkan Allure pada laporan.

DriverCreator adalah kelas yang menginisialisasi WebDriver (kelas paling penting untuk tes) tergantung pada parameter yang ditetapkan - lokal, solenoid atau ggr-selenoid. Selain itu, kelas mengeksekusi set Java Script yang diperlukan untuk pengujian kami. Semua aturan yang mengakses driver web harus diinisialisasi setelah kelas ini.

BrowserLogCatcher - kelas yang membaca pesan parah dari log browser, mencatatnya ke ELK (TestLogger) dan menerapkannya ke laporan Allure.

ScreenShooter - kelas yang untuk tes yang gagal mengambil screenshot layar browser dan menerapkannya pada laporan sebagai WebDriverRunner.getWebDriver (). GetScreenshotAs (OutputType.BYTES)

AttachmentFileSaver - kelas yang memungkinkan Anda untuk melampirkan laporan Allure satu set file acak yang diperlukan oleh logika bisnis tes. Digunakan untuk melampirkan file yang diunggah atau diunduh ke sistem.

FailClassifier adalah kelas khusus yang, dalam hal terjadi crash tes, mencoba untuk menentukan apakah crash ini disebabkan oleh masalah infrastruktur. Memeriksa keberadaan di layar (setelah crash) dari jendela modal khusus dari jenis "Kesalahan sistem No.XXXXXXXXXX telah terjadi", serta pesan sistem tipe 404 dan sejenisnya. Memungkinkan Anda untuk membagi tes jatuh menjadi crash bisnis (sesuai skenario) atau masalah sistem. Bekerja melalui ekstensi org.junit.rules.TestWatcher. # Metode gagal.

PendingRequestsCatcher adalah kelas khusus lain yang mencoba untuk mengklasifikasikan lebih lanjut apakah kerusakan itu disebabkan oleh layanan istirahat yang tidak lengkap, digantung atau sangat lama antara angular dan frontend web. Selain pengujian fungsional, memungkinkan untuk mengidentifikasi layanan istirahat bermasalah dan beku di bawah beban berat, serta stabilitas keseluruhan rilis. Untuk melakukan ini, kelas mencatat semua acara dengan permintaan istirahat beku yang diterima oleh ELK dengan meluncurkan js khusus di browser melalui driver web terbuka.

Templat Implementasi Kelas Tes


 package autotest.test.<sub-system>; @Feature("     TMS") @Story("    TMS") @Owner("       ") @TmsLink("    .   ") public class <   >_Test extends BaseTest { /** *           **/    Login orgTest; /**         **/    Login loginStep1;    ...    Login loginStepN;    /** *   -      -   * ...         **/      /** *    *              *    Utils.allure.message("     -", business_object) *     null,             . *             preconditions  actions    *  Utils.allure.message("      ", documentNumber) **/ @Step("  ") private void init(Login login) {    some_business_object = //         login        Utils.allure.message("     -", some_business_object)                           // ...             /**     */        loginStep1 = LoginFactory.get(_Some_Login_);    ...    loginStepN = LoginFactory.get(_Some_Login_); }    /** *       **/    @Test    @Filter("       JUnit")    @DisplayName("    TMS")    public void <   >_<>_<__>_Test() {  //            orgTest = LoginFactory.get(_Some_Login_);                //               init(orgTest);           //    -.                preconditions();               //             actions(orgTest); }    /** *        **/ @Step(" ") protected void preconditions() {    loginStep1.login();    new SomeAction().apply(someTestObject1, ..., someTestObjectN);        Utils.allure.message("   -      -", someTestObjectN)        ...    }    /** *        */ @Step(" ") protected void actions(Login testLogin) {    testLogin.reLogin();               //                new SomeAction().apply(someTestObject1, ..., someTestObjectN); } } 

Templat Implementasi Kelas Script Uji


 package autotest.business.actions.some_subsystem; public class SomeAction {            //   PageClassA pageA = new PageClassA(); PageClassB pageB = new PageClassB();    @Step("     TMS")    @Description("     TMS")    public void apply(someTestObject1, ..., someTestObjectN) {    //   TMS        step_1(...);        step_2(...);        ...        step_N(...);    }    @Step("  1    TMS")    private void step_1(...) {       pageA.createSomething(someTestObject1);// just as an example create }    @Step("  2    TMS")    private void step_2(...) {   pageA.checkSomething(someTestObject1);// just as an example }                       ... } 

Menerapkan Kelas Penyaringan Uji FilterTestRunner


Berikut ini adalah implementasi ekstensi BlockJUnit4ClassRunner untuk memfilter tes berdasarkan set tag sewenang-wenang.

 /** * Custom runner for JUnit4 tests. * Provide capability to do additional filtering executed test methods * accordingly information that could be provided by {@link FrameworkMethod} */ public class FilterTestRunner extends BlockJUnit4ClassRunner { private static final Logger LOGGER = Logger.getLogger(FilterTestRunner.class.getName()); public FilterTestRunner(Class<?> klass) throws InitializationError {    super(klass); } /** * This method should be used if you want to hide filtered tests completely from output **/ @Override protected List<FrameworkMethod> getChildren() {    //  ,        @Filter       TestFilter filter = TestFilterFactory.get();    List<FrameworkMethod> allMethods = super.getChildren();    List<FrameworkMethod> filteredMethod = new ArrayList<>();    for (FrameworkMethod method: allMethods) {        if (filter.test(method)) {            LOGGER.config("method [" + method.getName() +"] passed by filter [" + filter.toString() + "]" );            filteredMethod.add(method);        } else {            LOGGER.config("method [" + method.getName() +"] blocked by filter [" + filter.toString() + "]" );        }    }    return Collections.unmodifiableList(filteredMethod); } /** * This method should be used if you want to skip filtered tests but no hide them @Override protected boolean isIgnored(FrameworkMethod method) {    …    if (filter.test(method)) {        return super.isIgnored(method);    } else {     return true;  }} */ } 

Pada bagian selanjutnya, saya akan berbicara tentang bagaimana kami menerapkan proses mengunggah file dari wadah dengan browser ke kerangka uji, dan memecahkan masalah menemukan nama file yang diunduh oleh browser.

Ngomong-ngomong, kami akan dengan senang hati mengisi tim kami. Lowongan saat ini ada di sini .

Source: https://habr.com/ru/post/id480910/


All Articles