Otomasi Blok Bangunan Dasar - Pengujian
Rod Johnson

Saya bukan duta besar untuk menguji antarmuka web, tetapi esai ini lebih cenderung bermanfaat bagi kawan-kawan yang sudah memiliki pengalaman di bidang ini.
Ini juga akan berguna untuk pemula, karena Saya memberikan kode sumber di mana Anda dapat melihat bagaimana interaksi dengan selenium diatur dalam produk akhir.
Saya akan berbicara tentang bagaimana, dari awal, memiliki sedikit pengalaman pengembangan, saya menulis sebuah platform untuk menjalankan tes, dan tentang platform itu sendiri. Saya sendiri percaya bahwa produk saya ternyata sangat efektif, yang berarti akan bermanfaat bagi banyak orang dan memiliki tempat untuk dipertimbangkan.
Dari konsepnya
Proses pengujian tergantung pada sistem informasi.
Untuk mengingat konsep saya, perlu untuk memahami sistem yang saya fokuskan di tempat pertama - mereka adalah sistem di mana biasanya ada proses bisnis linier spesifik yang ditetapkan sebagai kunci ketika melakukan tes regresi.
Jadi, sistem seperti srm. Entitas bisnis utama adalah penawaran vendor. Pertimbangan utama dalam melakukan pengujian regresi adalah integritas proses bisnis.
Proses bisnis dimulai dari pendaftaran pemasok dalam sistem, kemudian pembuatan proposal komersial dilanjutkan - ia menuju ke tahap pertimbangan, yang dilakukan oleh berbagai jenis pengguna internal (dan setiap pengguna memiliki antarmuka yang unik) hingga keputusan mengenai pertimbangan proposal kepada pemasok dikembalikan.
Ternyata kita melalui sejumlah antarmuka yang berbeda, dan hampir selalu bekerja dengan yang berbeda. Bahkan - jika Anda hanya melihatnya secara langsung - sepertinya menonton rekaman video - mis. ini adalah proses yang memiliki awal dan akhir, dan itu benar-benar linier - tanpa cabang, saat menulis tes, kita selalu tahu hasil yang diharapkan. Yaitu Saya ingin mengatakan bahwa sudah melihat gambar ini, kita dapat menyimpulkan bahwa membuat tes polimorfik tidak mungkin berhasil. Mengingat hal ini, saat membuat platform untuk menjalankan tes, faktor kunci saya mengatur kecepatan penulisan tes.
Konsep yang saya tetapkan untuk diri saya sendiri:- Autotest harus dibuat secepat mungkin. Jika Anda mencapai ini secara kualitatif, maka aspek lain, seperti keandalan dan kemudahan penggunaan, harus datang sendiri.
- Tes harus dinyatakan secara deklaratif dan hidup terpisah dari kode. Saya bahkan tidak melihat opsi lain. Ini meningkatkan kecepatan penulisan, seperti jika Anda memiliki juru bahasa yang siap pakai - platform kami, maka Anda tidak perlu menambahkan apa pun nanti, Anda tidak perlu masuk ke kode lagi - secara umum, Anda bisa melupakan platform yang sudah selesai menggunakan IDE. Jadi tes lebih mudah untuk dipertahankan. Dalam bentuk ini, mereka lebih mudah belajar menulis, karena keterampilan pengembangan tidak diperlukan, tetapi hanya pemahaman tentang bahasa markup. Dalam formulir ini, mereka dapat dimengerti oleh semua peserta dalam proses.
Apa yang saya putuskan untuk ditolak pada awalnya:
- JANGAN bungkus sistem Anda dalam kerangka uji. Anda dapat memulai pelaksanaan suatu proses tanpa kerangka uji. "Anda ingin menciptakan sepeda!" - banyak yang akan mengatakan. Saya berpikir secara berbeda. Kerangka uji yang digunakan populer dibuat terutama untuk menguji kode dari dalam, dan kami akan menguji bagian luar sistem dari luar. Ini seperti jika saya memiliki sepeda jalan, dan saya harus turun gunung (kasar, tapi pemikirannya mencerminkan). Secara umum, kita akan menulis kerangka kerja sendiri - dengan blackjack dan ... (walaupun saya sadar bahwa, misalnya, JUnit 5 sudah jauh lebih disesuaikan untuk tugas-tugas seperti itu).
- Penolakan untuk menggunakan pembungkus untuk selenium. Sebenarnya, pustaka kunci itu sendiri kecil. Untuk memahami bahwa Anda perlu menggunakan 5 persen fungsinya, sambil menyekopnya sepenuhnya, itu akan memakan waktu beberapa jam. Berhentilah mencari di mana-mana cara untuk mengurangi kode dan membiasakan diri Anda dengan toilet. Di dunia modern, keinginan ini sering mengarah pada absurditas dan hampir selalu menyebabkan kerusakan pada fleksibilitas (maksud saya pendekatan untuk "menulis lebih sedikit kode" dan bukan kasus kerangka kerja arsitektur).
- Presentasi yang indah dari hasil tidak perlu. Memperkenalkan item ini, karena Saya tidak pernah berhadapan dengan ini. Ketika autotest selesai, saya perlu tahu 2 hal: hasil keseluruhan (positif / negatif), dan jika ada kesalahan - di mana tepatnya. Mungkin Anda masih perlu menyimpan statistik. Segala sesuatu yang lain dalam hal hasil BENAR-BENAR tidak penting. Untuk mempertimbangkan desain yang indah sebagai nilai tambah yang signifikan, atau menghabiskan waktu untuk desain yang indah ini pada tahap awal - merupakan pamer yang berlebihan.
Saya akan berbicara sedikit lebih banyak tentang tingkat perkembangan di perusahaan dan kondisi untuk membuat alat untuk sepenuhnya memperjelas beberapa detail.
Karena beberapa keadaan rahasia, saya tidak mengungkapkan perusahaan tempat saya bekerja.
Di perusahaan kami, pengembangan telah ada selama bertahun-tahun, dan oleh karena itu semua proses telah lama ditetapkan. Namun, mereka jauh di belakang tren saat ini.
Semua perwakilan TI memahami bahwa perlu untuk menutupi kode dengan tes, menulis skrip untuk autotest pada saat mengoordinasikan persyaratan untuk fungsionalitas masa depan, teknologi fleksibel secara signifikan menghemat waktu dan sumber daya, dan CI yang hanya mengambil dan menyederhanakan kehidupan. Tapi sejauh ini hanya perlahan-lahan mencapai kita ...
Begitu juga layanan kontrol kualitas perangkat lunak - semua tes dilakukan secara manual, jika Anda melihat proses "dari atas" - ini adalah "hambatan" dari seluruh proses pengembangan.
Deskripsi perakitan
Platform ini ditulis dalam Java menggunakan JDK 12
Alat Infrastruktur Utama - Selenium Web Driver, OJDBC
Agar aplikasi berfungsi, browser FireFox versi 52 harus diinstal pada PC
Komposisi Pembuatan Aplikasi

Dengan aplikasi ini, 3 folder dan 2 file diperlukan:
β’ Folder
BuildKit - berisi:
- jdk12, di mana aplikasi diluncurkan (JVM);
- geckodriver.exe - untuk Selenium Web Driver berfungsi dengan browser FireFox;
- SprintAutoTest.jar - langsung contoh aplikasi
β’ Folder laporan - laporan disimpan padanya setelah aplikasi menyelesaikan kasus uji. Itu juga harus berisi folder ErrorScreens, di mana tangkapan layar disimpan jika terjadi kesalahan
β’ Folder
TestSuite - paket web, javascripts, satu set kasus uji (mengisi folder ini akan dibahas secara rinci secara terpisah)
β’ file config.properties - berisi konfigurasi untuk menghubungkan ke database Oracle dan nilai ekspektasi eksplisit untuk WebDriverWait
β’ starter.bat - file untuk meluncurkan aplikasi (dimungkinkan untuk meluncurkan aplikasi secara otomatis tanpa menetapkan TestCase secara manual jika Anda memasukkan nama TestCase sebagai parameter di akhir).
Deskripsi singkat aplikasi
Aplikasi ini dapat diluncurkan dengan parameter (nama TestCase) atau tanpa itu - dalam hal ini, Anda harus memasukkan nama kotak uji di konsol sendiri.
Contoh konten umum file kelelawar untuk dijalankan tanpa parameter : mulai "peluncur AutoTest"% cd% \ BuildKit \ jdk-12 \ bin \ java.exe -Xmx768M -jar --enable-preview% cd% \ BuildKit \ SprintAutoTest.jarPada saat peluncuran aplikasi secara umum, ini terlihat pada file xml yang terletak di direktori "\ TestSuite \ TestCase" (tanpa melihat isi dari subfolder). Dalam kasus ini, validasi utama file xml ke kebenaran struktur terjadi (yaitu, semua tag dari sudut pandang markup xml sudah benar), dan nama-nama yang ditunjukkan dalam tag "testCaseName" diambil, setelah itu pengguna diminta memasukkan salah satu nama yang mungkin untuk pengujian yang tersedia. kasus. Jika ada entri yang salah, sistem akan meminta Anda untuk memasukkan nama lagi.
Setelah nama TestCase diterima, model internal dibangun, yang merupakan sekelompok TestCase (skrip uji) - WebPackage (penyimpanan elemen) dalam bentuk objek java. Setelah membangun model, TestCase (objek yang dapat dieksekusi dari program) dibangun langsung. Pada tahap konstruksi TestCase, validasi sekunder juga terjadi - diperiksa bahwa semua formulir yang ditentukan dalam TestCase berada di WebPackage terkait dan bahwa semua elemen yang ditentukan dalam tindakan berada di WebPackage dalam halaman yang ditentukan. (Struktur TestCase dan WebPackage dijelaskan secara rinci di bawah)
Setelah TestCase dibangun, skrip berjalan langsung
Algoritma operasi skrip (logika kunci)
TestCase adalah kumpulan entitas Action, yang pada gilirannya adalah kumpulan entitas Event.
Testcase
-> Daftar {Aksi}
-> Daftar {Acara}Ketika TestCase dimulai, Action dimulai secara berurutan (setiap Action mengembalikan hasil yang logis)
Ketika Aksi dimulai, Acara berurutan dimulai (setiap Acara mengembalikan hasil yang logis)
Hasil dari setiap Acara disimpan.
Dengan demikian, tes ini selesai baik ketika semua tindakan berhasil diselesaikan, atau jika tindakan dikembalikan salah.
* Mekanisme kerusakan
Karena sistem saya sedang diuji adalah kuno dan telah menangkap kesalahan / bug yang bukan kesalahan, dan beberapa peristiwa tidak berfungsi pertama kali, platform memiliki mekanisme yang dapat berangkat dari konsep tes ketat linier di atas (namun, sangat diketik). Saat menangkap kesalahan seperti itu, dimungkinkan untuk mengulangi kasus terlebih dahulu dan melakukan tindakan tambahan untuk dapat mengulangi tindakanDi akhir aplikasi, laporan dihasilkan, yang disimpan di direktori "\ Laporan". Jika terjadi kesalahan, tangkapan layar diambil, yang disimpan di "\ Laporan \ ErrorScreens"
Mengisi TestSuite
Jadi, uraian tes. Seperti yang telah disebutkan, parameter utama yang diperlukan untuk menjalankan adalah nama tes yang akan dijalankan. Nama ini disimpan dalam file xml di direktori "/ TestSuite / TestCase". Semua skrip uji disimpan dalam direktori ini. Jumlah mereka bisa berapa. Nama kasus uji diambil bukan dari nama file, tetapi dari tag "testCaseName" di dalam file.
TestCase menetapkan apa yang sebenarnya akan dilakukan - mis. tindakan. Dalam direktori "/ TestSuite / WebPackage" dalam file xml semua pencari lokasi disimpan. Yaitu semua dalam tradisi terbaik - tindakan disimpan secara terpisah, pencari formulir web secara terpisah.
TestCase juga menyimpan nama WebPackage di tag "webPackageName".
Total gambar sudah ada di sana. Untuk menjalankan, Anda harus memiliki 2 file xml: TestCase dan WebPackage. Mereka membuat banyak. WebPackage independen - pengidentifikasi adalah nama di tag "webPackageName". Oleh karena itu, inilah aturan pertama - nama TestCase dan WebPackage harus unik. Yaitu sekali lagi - pada kenyataannya, pengujian kami adalah sekelompok file TestCase dan WepPackage, yang terhubung dengan nama WebPackage, yang ditentukan dalam TestCase. Dalam praktiknya, saya mengotomatisasi satu sistem dan saya merajut semua kasus pengujian saya ke satu WebPackage di mana saya memiliki tumpukan deskripsi dari semua bentuk.
Lapisan dekomposisi logis berikutnya didasarkan pada pola seperti Page Object.
Objek HalamanHalaman Obyek adalah salah satu solusi arsitektur yang paling berguna dan digunakan dalam otomatisasi. Pola desain ini membantu merangkum pekerjaan dengan elemen halaman individual. Page Object, seolah-olah, mensimulasikan halaman aplikasi yang sedang diuji sebagai objek.
Pemisahan logika dan implementasi
Ada perbedaan besar antara logika pengujian (apa yang harus diperiksa) dan implementasinya (cara memeriksa). Contoh skenario pengujian: "Pengguna memasukkan nama pengguna atau kata sandi yang salah, menekan tombol masuk, menerima pesan kesalahan." Skrip ini menjelaskan logika pengujian, sementara implementasinya mencakup tindakan seperti mencari bidang input pada halaman, mengisinya, memeriksa kesalahan, dll. Dan jika, misalnya, metode menampilkan perubahan pesan kesalahan, maka ini tidak akan mempengaruhi skrip pengujian, Anda juga perlu memasukkan data yang salah, tekan tombol masuk dan periksa kesalahan. Tetapi ini akan secara langsung mempengaruhi implementasi tes - akan perlu untuk mengubah metode yang menerima dan memproses pesan kesalahan. Dengan memisahkan logika tes dari implementasinya, autotests menjadi lebih fleksibel dan, sebagai aturan, lebih mudah untuk dipertahankan.
*! Tidak dapat dikatakan bahwa pendekatan arsitektur ini telah sepenuhnya diterapkan. Ini hanya masalah penguraian deskripsi skrip uji halaman demi halaman, yang membantu untuk menulis tes lebih cepat dan menambahkan pemeriksaan otomatis tambahan pada semua halaman, merangsang deskripsi yang benar dari pelacak (sehingga mereka tidak sama pada halaman yang berbeda) dan membangun struktur logis dari tes yang "indah". Platform itu sendiri diimplementasikan dengan prinsip "Arsitektur Bersih"
Selanjutnya, saya akan mencoba untuk tidak merinci struktur WebPackage dan TestCase. Bagi mereka, saya membuat skema DTD untuk WebPackage dan XSD 1.1 untuk TestCase.
! PENTING
Dengan mempertahankan skema DTD dan XSD, konsep penulisan tes cepat diimplementasikan.
Saat menulis WebPackage dan TestCase secara langsung, Anda harus menggunakan Editor xml dengan fungsi validasi DTD dan XSD real-time bawaan dengan pembuatan tag otomatis, yang akan membuat proses penulisan uji otomatis terotomatisasi secara otomatis (semua tag yang diperlukan akan diganti secara otomatis, daftar drop-down akan ditampilkan untuk nilai atribut nilai yang mungkin, sesuai dengan jenis acara, tag terkait akan dihasilkan) .
Ketika skema ini "disekrup" ke file xml itu sendiri, maka Anda bisa melupakan kebenaran struktur file xml, jika Anda menggunakan lingkungan khusus. Pilihan saya jatuh pada Editor XLX oXygen. Sekali lagi - tanpa menggunakan program seperti itu, Anda tidak akan mengerti esensi dari kecepatan menulis. Ide sangat tidak cocok untuk ini. itu tidak menangani konstruksi "alternatif" XSD 1.1, yang merupakan kunci untuk TestCase.
Paket web
WebPackaege - file xml yang menjelaskan elemen-elemen formulir web, yang terletak di direktori "\ TestSuite \ WebPackage". (bisa ada file sebanyak yang Anda suka. Nama file bisa apa saja - hanya konten yang penting).
DTD (disisipkan di awal dokumen):<!DOCTYPE webPackage [ <!ELEMENT webPackage (webPackageName, forms)> <!ELEMENT webPackageName (#PCDATA)> <!ELEMENT forms (form+)> <!ELEMENT form (formName, elements+)> <!ELEMENT formName (#PCDATA)> <!ELEMENT elements (element+)> <!ELEMENT element (name, locator)> <!ATTLIST element type (0|1|2|3|4|5|6|7) #REQUIRED> <!ATTLIST element alwaysVisible (0|1) #IMPLIED> <!ELEMENT name (#PCDATA)> <!ELEMENT locator (#PCDATA)> <!ATTLIST locator type (1|2) #IMPLIED> ]>
Secara umum, itu terlihat kurang lebih <webPackage> <webPackageName>_</webPackageName> <forms> <form> <formName>______</formName> <elements> <element type="2" alwaysVisible="1"> <name>_</name> <locator type="2">.//div/form/div/div/form/table/tbody/tr/td[text()=""]/following-sibling::td/input</locator> </element> <element type="2"> <name>__</name> <locator>.//div/form/div/div/form/table/tbody/tr/td[text()=""]/following-sibling::td/input</locator> </element> ....... </elements> </form> ....... </forms> </webPackage>
Seperti yang telah disebutkan, sehingga elemen-elemennya tidak ada di heap - semuanya diurai menurut formulir web
Entitas kuncinya adalah
<element>
Tag elemen memiliki 2 atribut:
Atribut
type diperlukan dan menentukan tipe elemen. Di platform, setel tipe byte
Saat ini, khusus untuk saya sendiri, saya menerapkan jenis platform berikut:
β’ 0 - tidak memiliki arti fungsional, biasanya semacam prasasti
β’ 1 - tombol (tombol)
β’ 2 - bidang input
β’ 3 - kotak centang (kotak centang)
β’ 4 - daftar drop-down (pilih) - tidak benar-benar diterapkan, tetapi meninggalkan tempat untuk itu
β’ 5 - untuk daftar drop-down srm: tulis nama, tunggu nilainya muncul - pilih sesuai dengan templat xpath spesifik - jenis khusus untuk sistem saya
β’ Pilih 6 - srm - digunakan pada fungsi-fungsi khas seperti pencarian, dll. - ketik khusus untuk sistem saya
Atribut
alwaysVisible - opsional - menunjukkan apakah suatu elemen selalu ada pada formulir, dapat digunakan selama validasi awal / akhir Aksi (mis., Dalam mode otomatis, Anda dapat memverifikasi bahwa ketika Anda membuka formulir, itu berisi semua elemen yang selalu ada di dalamnya, ketika menutup bentuk, semua elemen ini telah hilang)
Nilai yang mungkin:
- 0 - secara default (atau jika atribut tidak disetel) - elemen mungkin tidak ada di halaman (jangan divalidasi)
- 1 - elemen selalu ada di halaman
Atribut
tipe opsional opsional diterapkan dengan tag locator
Nilai yang mungkin:
- 1 - mencari elemen dengan id (masing-masing, tentukan hanya id di locator)
- 2 - secara default (atau jika atribut tidak disetel) - cari di xpath - disarankan hanya menggunakan pencarian di xpath, karena Metode ini menggabungkan hampir semua kelebihan sisanya dan bersifat universal
Testcase
TestCase - file xml yang secara langsung menggambarkan skrip uji terletak di direktori "\ TestSuite \ TestCase" (mungkin ada file sebanyak yang Anda suka. Nama file dapat berupa apa saja - hanya masalah konten).
Sirkuit XSD: <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="testCase"> <xs:complexType> <xs:sequence> <xs:element name="testCaseName" type="xs:string"/> <xs:element name="webPackageName" type="xs:string"/> <xs:element name="actions" type="actionsType"/> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="actionsType"> <xs:sequence> <xs:element name="action" type="actionType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="actionType"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="orderNumber" type="xs:positiveInteger"/> <xs:element name="runConfiguration" type="runConfigurationType"/> </xs:sequence> </xs:complexType> <xs:complexType name="runConfigurationType"> <xs:sequence> <xs:element name="formName" type="xs:string"/> <xs:element name="repeatsOnError" type="xs:positiveInteger" minOccurs="0"/> <xs:element name="events" type="eventsType"/> <xs:element name="exceptionBlock" type="eventsType" minOccurs="0"/> </xs:sequence> <xs:attribute name="openValidation" use="required"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="closeValidation" use="required"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> <xs:complexType name="eventBaseType"> <xs:sequence> <xs:element name="orderNumber" type="xs:positiveInteger"/> </xs:sequence> <xs:attribute name="type" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="goToURL"/> <xs:enumeration value="checkElementsVisibility"/> <xs:enumeration value="checkElementsInVisibility"/> <xs:enumeration value="fillingFields"/> <xs:enumeration value="clickElement"/> <xs:enumeration value="dbUpdate"/> <xs:enumeration value="wait"/> <xs:enumeration value="scrollDown"/> <xs:enumeration value="userInput"/> <xs:enumeration value="checkInputValues"/> <xs:enumeration value="checkQueryResultWithUtilityValue"/> <xs:enumeration value="checkFieldsPresenceByQueryResult"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="invertResult" use="optional" default="0"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="hasExceptionBlock" use="optional" default="0"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> <xs:complexType name="eventsType"> <xs:sequence> <xs:element name="event" type="eventBaseType" maxOccurs="unbounded"> <xs:alternative test="@type='goToURL'" type="eventGoToURL"/> <xs:alternative test="@type='checkElementsVisibility'" type="eventCheckElementsVisibility"/> <xs:alternative test="@type='checkElementsInVisibility'" type="eventCheckElementsVisibility"/> <xs:alternative test="@type='fillingFields'" type="eventFillingFields"/> <xs:alternative test="@type='checkInputValues'" type="eventFillingFields"/> <xs:alternative test="@type='clickElement'" type="eventClickElement"/> <xs:alternative test="@TYPE='dbUpdate'" type="eventRequest"/> <xs:alternative test="@type='wait'" type="utilityValueInteger"/> <xs:alternative test="@type='scrollDown'" type="eventClickElement"/> <xs:alternative test="@type='userInput'" type="eventClickElement"/> <xs:alternative test="@type='checkQueryResultWithUtilityValue'" type="eventRequestWithValue"/> <xs:alternative test="@type='checkFieldsPresenceByQueryResult'" type="eventRequestWithValue"/> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="eventGoToURL"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="url" type="xs:anyURI"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventCheckElementsVisibility"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="fields" type="fieldType"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventFillingFields"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="fields" type="fieldTypeWithValue"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventClickElement"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="elementName" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventRequest"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="dbRequest" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="utilityValueInteger"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="utilityValue" type="xs:positiveInteger"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventRequestWithValue"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="dbRequest" type="xs:string"/> <xs:element name="utilityValue" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="fieldType"> <xs:sequence> <xs:element name="field" maxOccurs="unbounded"> <xs:complexType> <xs:choice> <xs:element name="element" type="xs:string"/> <xs:element name="xpath" type="xs:string"/> </xs:choice> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="fieldTypeWithValue"> <xs:sequence> <xs:element name="field" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="element" type="xs:string"/> <xs:element name="value" type="valueType"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="valueType"> <xs:complexContent> <xs:extension base="xs:anyType"> <xs:attribute name="type" use="optional" default="1"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="2"/> <xs:enumeration value="3"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:extension> </xs:complexContent> </xs:complexType> </xs:schema>
Tampilan umum: <!DOCTYPE testCase SYSTEM "./TestSuite/TestCase/entities.dtd" []> <testCase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="testShema.xsd"> <testCaseName>__testCase</testCaseName> <webPackageName>_webPackage__webPackageName</webPackageName> <actions> <action> <name> </name> <orderNumber>10</orderNumber> <runConfiguration openValidation="1" closeValidation="1"> <formName>______</formName> <events> <event type="goToURL"> <orderNumber>10</orderNumber> <url>&srmURL;</url> </event> ....... </events> </runConfiguration> </action> ....... </actions> </testCase>
Di sini, di baris ini Anda bisa melihat cara mempercepat skema xsd sehingga Editor XML melihatnya:
<testCase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="testShema.xsd">
Di TestCase, saya juga menggunakan entitas DTD yang disimpan secara terpisah di direktori yang sama - file dengan ekstensi .dtd. Di dalamnya, saya menyimpan hampir semua data - konstanta. Saya juga membangun logika sedemikian rupa sehingga untuk meluncurkan tes baru, dan selama tes, entitas unik baru dibuat, pesawat ruang angkasa baru terdaftar, itu cukup untuk mengubah 1 digit dalam file ini.
Strukturnya sangat sederhana - saya akan memberikan contoh: <?xml version="1.0" encoding="UTF-8"?> <!ENTITY mainNumber '040'> <!ENTITY mail '@mail.ru'> <!ENTITY srmURL 'https://srm-test.ru'>
Konstanta seperti itu dimasukkan ke dalam nilai tag sebagai berikut:
<url>&srmURL;</url>
- dapat digabungkan.
! Rekomendasi - saat menulis testCase, Anda harus menentukan entitas DTD ini di dalam dokumen, dan setelah semuanya berjalan dengan stabil, transfer ke file yang terpisah. Editor xml saya mengalami kesulitan dengan ini - tidak dapat menemukan DTD dan tidak memperhitungkan XSD, jadi saya merekomendasikan ini
testCasetestCase - tag induk paling banyak mengandung:
- testCaseName - nama kasus uji kami, parameter ini diteruskan ke input aplikasi
- webPackageName - nama WebPackage, yang ditentukan dalam webPackageName (lihat paragraf di atas di WebPackage)
- tindakan - wadah entitas tindakan
tindakanBerisi:
- nama - nama - disarankan untuk menentukan nama formulir dan tindakan utama - apa dan mengapa
- orderNumber - nomor seri - parameter yang diperlukan untuk menyortir tindakan (diperkenalkan karena fakta bahwa ketika parsing xml di java menggunakan alat tertentu, parsing dapat dilakukan dalam lingkungan multi-berulir, sehingga pesanan dapat berjalan) - saat menentukan tindakan selanjutnya, Anda dapat melompat - yaitu ketika menyortir, itu hanya penting "lebih / kurang", dan jadi mungkin untuk melakukan tindakan antara yang sudah dijelaskan tanpa perlu mengubah seluruh penomoran
- runConfiguration - deskripsi aktual tentang apa yang akan terjadi sebagai bagian dari tindakan
jalankan KonfigurasiBerisi:
- Atribut openValidation - opsional, standarnya adalah "0"
- 0 - jangan melakukan validasi formulir awal
- 1 - validasi formulir awal
- atribut closeValidation - opsional, standarnya adalah "0"
- 0 - jangan melakukan validasi bentuk akhir
- 1 - validasi bentuk akhir
- formName - nama formulir di mana tindakan akan dilakukan - nilai formName dari WebPackage
- repeatsOnError - opsional, menunjukkan berapa banyak pengulangan yang harus dilakukan jika terjadi kegagalan
- acara - wadah entitas acara
- exceptionBlock - opsional - wadah entitas acara yang dieksekusi jika terjadi kesalahan
acaraUnit struktural minimum - entitas ini menunjukkan tindakan apa yang dilakukan
Setiap acara adalah spesial, dapat memiliki tag dan atribut unik.
Tipe dasar berisi:
- atribut type - menunjukkan tipe elemen
- atribut hasExceptionBlock adalah atribut opsional, secara default "0" diperlukan untuk menerapkan mekanisme kegagalan - atribut menunjukkan bahwa kita dapat mengharapkan kesalahan pada acara ini
- 0 - tidak ada kesalahan yang diharapkan
- 1 - kesalahan yang mungkin terjadi pada tindakan
- atribut invertResult - atribut opsional, default ke "0" - atribut menunjukkan bahwa perlu untuk mengubah hasil acara
- 0 - tinggalkan hasil acara
- 1 - ubah hasil acara menjadi sebaliknya
*! Mekanisme untuk menggambarkan kesalahan yang diharapkanBiarkan saya memberi Anda contoh sepele di mana saya menggunakannya untuk pertama kalinya dan apa yang harus dilakukan untuk membuatnya berfungsi.
Kasus: Input Captcha. Saat ini, saya tidak bisa mengotomatisasi, jadi, untuk memeriksa robot mogok - mereka tidak menulis layanan tes captcha kepada saya (tetapi lebih mudah bagi saya untuk membuat jaringan saraf untuk pengakuan))) Jadi, kita dapat membuat kesalahan ketika masuk. Dalam hal ini, saya membuat acara kontrol di mana saya memeriksa bahwa kami tidak memiliki elemen - pemberitahuan tentang kode kontrol yang salah, saya meletakkan atribut hasExceptionBlock di atasnya. Sebelumnya, saya meminta tindakan bahwa kami dapat memiliki beberapa pengulangan (5) dan setelah semua, saya menulis exceptionBlock, di mana saya menulis bahwa saya harus menekan tombol keluar untuk pemberitahuan, dan kemudian tindakan itu diulang.
Contoh dari konteks saya.
Inilah cara saya mendaftarkan acara:
<event type="checkElementsInVisibility" hasExceptionBlock="1"> <orderNumber>57</orderNumber> <fields> <field> <element>___</element> </field> </fields> </event>
Dan di sini pengecualianBlokir setelah acara
<exceptionBlock> <event type="clickElement"> <orderNumber>10</orderNumber> <elementName>_____</elementName> </event> </exceptionBlock>
Dan ya, tindakan pada satu halaman dapat diuraikan menjadi beberapa tindakan.
+ yang memperhatikan 2 parameter dalam konfigurasi: defaultTimeOutsForWebDriverWait, lowTimeOutsForWebDriverWait. Jadi itu sebabnya mereka. Karena Saya memiliki seluruh driver web dalam satu singleton, dan saya tidak ingin membuat WebDriverWait baru setiap kali, maka saya punya satu yang cepat dan itu dalam kasus kesalahan (baik, atau jika Anda hanya meletakkan hasExceptionBlock = "1", maka itu akan menjadi bodoh dengan sedikit waktu tunggu eksplisit) - yah, Anda harus setuju, tunggu sebentar untuk memastikan bahwa pesan tidak keluar kome faut, serta membuat WebDriverWait baru setiap kali. Nah, situasi ini di sisi mana tidak menempel memerlukan penopang - Saya memutuskan untuk melakukannya.
Jenis acara
Di sini saya akan memberikan set minimal acara saya, seperti set scout, dengan mana saya dapat menguji hampir semua yang ada di sistem saya.
Dan sekarang, mudah bagi kodenya untuk memahami apa acara itu dan bagaimana acara itu dibuat. Kode dasarnya mengimplementasikan framework. Saya memiliki 2 kelas - DataBaseWrapper dan SeleniumWrapper. Di kelas-kelas ini, interaksi dengan komponen infrastruktur dijelaskan, dan fitur platform juga tercermin. Saya akan memberikan antarmuka yang mengimplementasikan SeleniumWrapper
package logic.selenium; import models.ElementWithStringValue; import models.webpackage.Element; import org.openqa.selenium.WebElement; public interface SeleniumService { void initialization(boolean webDriverWait); void nacigateTo(String url); void refreshPage(); boolean checkElementNotPresent(Element element); WebElement findSingleVisibleElement(Element element); WebElement findSingleElementInDOM(Element element); void enterSingleValuesToWebField(ElementWithStringValue element); void click(Element element); String getInputValue(Element element); Object jsReturnsValue(String jsFunction);
Ini menjelaskan semua fitur dari platform selenium dan overlay chip - yah, sebenarnya chip utama adalah metode "enterSingleValuesToWebField". Ingatlah bahwa kita di WebPackage menentukan jenis elemen. Jadi, bagaimana bereaksi terhadap tipe ini ketika mengisi kolom ditulis di sini. Kami menulis 1 kali dan lupa. Metode di atas harus diperbaiki untuk diri Anda sendiri. Misalnya, tipe 5 dan 6, yang saat ini berlaku, hanya cocok untuk sistem saya. Dan jika Anda memiliki hal seperti filter dan Anda perlu memfilter banyak, dan ini tipikal (dalam aplikasi web Anda), tetapi untuk menggunakannya Anda harus terlebih dahulu memindahkan mouse di atas bidang, tunggu beberapa bidang muncul, beralih ke beberapa, tunggu ada sesuatu, lalu pergi ke sana dan masukkan ... Bodoh meresepkan mekanisme tindakan 1 kali, memberikan jenis yang unik untuk ini semua dalam struktur saklar - jangan repot-repot lebih lanjut - dapatkan metode polimorfik untuk semua filter aplikasi serupa.
Jadi, dalam paket "package logic.testcase.events" ada kelas abstrak yang menggambarkan tindakan umum dari acara tersebut. Untuk membuat acara unik Anda sendiri, Anda perlu membuat kelas baru, mewarisi dari kelas abstrak ini, dan Anda sudah memiliki dataBaseService dan seleniumService di kit - dan kemudian Anda menentukan data apa yang Anda butuhkan dan apa yang harus dilakukan dengan itu. Sesuatu seperti itu. Nah dan karenanya, setelah membuat acara baru, Anda harus menyelesaikan kelas pabrik TestCaseActionFactory dan, jika mungkin, skema XSD. Nah, jika atribut baru ditambahkan - modifikasi model itu sendiri. Bahkan, sangat mudah dan cepat.
Jadi, satu set pengintai.
goToURL - biasanya tindakan pertama - klik pada tautan yang ditentukan
Contoh: <event type="goToURL"> <orderNumber>10</orderNumber> <url>testURL</url> </event>
fillingFields - Mengisi elemen yang ditentukan
Tag khusus:
- bidang - wadah entitas entitas
- bidang - berisi tag elemen
- elemen - menunjukkan nama elemen dari webPackage
- value - nilai apa yang ditunjukkan, memiliki atribut tipe opsional (jika elemennya kotak centang, maka salah satu nilai ditunjukkan: "centang" atau "hapus centang")
- ketik atribut - menunjukkan cara mengambil nilai, opsional, nilai default adalah "1"
- 1 - nilai yang ditentukan diambil
- 2 - dalam hal ini, fungsi JS yang ditentukan dari direktori "\ TestSuite \ JS" dijalankan! PENTING - nama file txt diindikasikan, tanpa ".txt" (dan sejauh ini saya telah menemukan aplikasi untuk fungsi js sejauh ini hanya dalam bentuk ini - saya menggunakannya di satu tempat untuk menghasilkan penginapan acak, tetapi spektrum aplikasi yang mungkin luas)
- 3 - dalam hal ini, kueri dalam database ditunjukkan sebagai nilai, dan program menggantikan hasil pertama dari kueri ini
Contoh: <event type="fillingFields"> <orderNumber>10</orderNumber> <fields> <field> <element>test</element> <value>test</value> </field> </fields> </event>
checkElementsVisibility - memeriksa apakah elemen yang ditentukan ada pada formulir (yaitu, terlihat, dan bukan hanya di DOM). Dalam atribut bidang, elemen dari WebPackage atau langsung xpath dapat ditentukan
Contoh: <event type="checkElementsVisibility"> <orderNumber>10</orderNumber> <fields> <field> <element>test</element> </field> <field> <xpath>test</xpath> </field> </fields> </event>
checkElementsInVisibility - mirip dengan checkElementsVisibility, tetapi sebaliknya
clickElement - klik pada elemen yang ditentukan
Contoh: <event type="clickElement"> <orderNumber>10</orderNumber> <elementName>test</elementName> </event>
checkInputValues - periksa nilai yang dimasukkan
Contoh: <event type="checkInputValues"> <orderNumber>10</orderNumber> <fields> <field> <element>test</element> <value>test</value> </field> </fields> </event>
dbUpdate - melakukan pembaruan dalam basis data (
oXygen bereaksi aneh terhadap 1 jenis aktivitas dbUpdate - Saya tidak tahu apa yang harus dilakukan dengan itu dan tidak mengerti mengapa )
Contoh: <event type="dbUpdate"> <orderNumber>10</orderNumber> <dbRequest>update - </dbRequest> </event>
CheckQueryResultWithUtilityValue - periksa nilai yang dimasukkan oleh pengguna dengan nilai dari database
Contoh: <event type="checkQueryResultWithUtilityValue"> <orderNumber>10</orderNumber> <dbRequest>select ...</dbRequest> <utilityValue>test</utilityValue> </event>
checkFieldsPresenceByQueryResult - periksa keberadaan elemen pada formulir dengan xpath oleh pola. Jika pola yang diinginkan tidak ditentukan, maka pencarian akan terjadi sesuai dengan pola .//* [text () [berisi (normalize-space (.), "$")]], Di mana alih-alih "$" akan ada nilai dari database. Saat menggambarkan pola Anda sendiri, Anda harus menunjukkan "$" di tempat Anda ingin meletakkan nilai dari database. Dalam sistem saya ada yang disebut grid di mana ada nilai-nilai yang biasanya terbentuk dari beberapa jenis tampilan. Acara ini untuk menguji kisi-kisi tersebut
Contoh: <event type="checkFieldsPresenceByQueryResult"> <orderNumber>10</orderNumber> <dbRequest>test</dbRequest> <utilityValue></utilityValue> </event>
Tunggu - semuanya sederhana - menunggu jumlah milidetik yang ditentukan. Sayangnya, meskipun ini dianggap sebagai penopang, saya akan mengatakan dengan pasti - kadang-kadang tidak mungkin dilakukan tanpa itu
Contoh: <event type="wait"> <orderNumber>10</orderNumber> <utilityValue>1000</utilityValue> </event>
scrollDown - gulir ke bawah dari elemen yang ditentukan. Ini dilakukan dengan cara ini: mengklik elemen yang ditentukan dan menekan tombol "PgDn". Dalam kasus saya di mana saya harus menggulir ke bawah, itu berfungsi dengan baik:
Contoh: <event type="scrollDown"> <orderNumber>10</orderNumber> <elementName>test</elementName> </event>
userInput - masukkan nilai dalam elemen yang ditentukan. Satu-satunya perangkat semi otomatis di otomatisasi saya, hanya digunakan untuk captcha. Elemen untuk memasukkan nilai ke ditunjukkan. Nilai dimasukkan dalam kotak dialog sembulan.
Contoh: <event type="userInput"> <orderNumber>10</orderNumber> <elementName>capch_input</elementName> </event>
Tentang kodenya
Maka, saya mencoba membuat peron sesuai dengan prinsip Arsitektur Bersih Paman Bob.
Paket:
aplikasi - inisialisasi dan meluncurkan + konfigurasi dan laporan (jangan memarahi saya untuk kelas Laporan - inilah yang membuatnya secepat mungkin, lalu secepat mungkin)
logika - layanan kunci logika + dari Selenium dan DB. Ada beberapa acara.
model - POJO dalam XML dan semua kelas objek pembantu
utils - singleton untuk selenium dan db
Untuk menjalankan kode, Anda harus mengunduh jdk 12 dan menentukan di mana-mana agar chip-nya menyala. Dalam Idea, ini dilakukan melalui Struktur Proyek -> Modul dan Proyek. Juga jangan lupa tentang pelari Maven.
Dan ketika Anda mulai di file bat, tambahkan --enable-preview. Contohnya adalah.Untuk memulai semuanya, melewati JDK Anda harus mengunduh driver ojdbc dan memasukkan dzharnik ke direktori "SprintAutoTest \ src \ lib". Saya tidak menyediakannya, karena sekarang semuanya serius di Oracle sana - untuk mengunduhnya perlu mendaftar, tapi saya yakin semua orang akan mengatasinya (well, pastikan semua folder dibuat, kalau tidak laporan tidak akan disimpan)Ringkasan
Jadi, kami memiliki peluncur ujian, tes menulis yang sangat cepat. Selama minggu kerja, saya dapat mengotomatiskan 1,5 jam kerja manual, yang dilakukan oleh robot dalam 5-6 menit. Ini adalah sekitar 3700 baris dari test case yang digabungkan dan 830 elemen yang dijelaskan (lebih dari 4800 baris). Angka-angka itu kasar, jadi tidak diukur, tetapi mereka yang terlibat dalam otomatisasi harus memahami bahwa ini adalah angka yang sangat tinggi, terutama untuk sistem robot-tidak ramah. Pada saat yang sama, saya menguji semuanya - logika bisnis, di sepanjang jalan saya melakukan beberapa tes negatif untuk kebenaran atribut yang diisi, dan sebagai bonus saya memeriksa setiap formulir web yang saya tidak malas, dan menjelaskan semua elemen fungsional dan kunci, mereka diperlukan secara mandiri saya atau tidak (Penyimpangan kecil - saya menggunakan closeValidation terutama hanya ketika menulis tes.Ketika stabil, dan jelas bahwa pelacak tidak berpotongan, saya mematikannya untuk semua tindakan, sehingga prosesnya berjalan lebih cepat).Sekilas, tampaknya ada banyak garis xml, tetapi dalam praktiknya dihasilkan secara semi-otomatis, dan kesalahan hanya dapat dibuat dalam parameter yang dimasukkan langsung (karena sebenarnya kita memiliki 2 tingkat validasi - yang pertama adalah xml skema, yang kedua memeriksa keberadaan formulir dan elemen yang ditentukan pada awal TestCase).Dari minus - tidak ada batasan yang jelas dari tes. Dengan demikian, mereka hilang dan Anda dapat menyalahkan saya bahwa ini hanyalah peluncur makro, bukan tes. Saya mengatakan ini:Di platform, tes secara konseptual dibagi dari beberapa sudut pandang menjadi beberapa tingkat abstraksi:- + β Β« Β» + β ( β .. -)
- ( action β event c + )
- , , β -. , β . , . , β ,
- setiap tindakan pada halaman adalah unit test (mengembalikan hasil tunggal benar atau salah)
Jika Anda membandingkan pendekatan saya dengan sesuatu, maka minus, misalnya, Mentimun populer dan konsep BDD lebih penting bagi saya (tepatnya ketika kami menguji yang seperti sistem saya):- Kami tidak dapat menjamin kinerja pengujian saat menguji aplikasi web yang tidak stabil. Yaitu dalam kasus saya, untuk sebagian besar pengujian kami tidak dapat menjamin eksekusi mereka, dan mereka akan jatuh pada "Kapan", yang menurut saya secara umum tidak dapat diterima, jika kami menggambarkan pengujian dengan serangkaian tes.
- Nah dan di mana-mana ini contoh yang sangat besar dengan login diberikan. Ya, untuk semua latihan saya, justru di login bahwa tidak pernah ada kesalahan (walaupun itu pasti harus dibahas, itu pasti). Dan contohnya bagus, tetapi untuk sisa tes, Anda perlu memahat kruk tak berujung dari Given dan When - dalam sistem yang saya berikan untuk pengujian nyata, akan diperlukan 99% untuk menggambarkan kondisi perantara, sementara kita sampai pada tes ini sendiri - banyak masalah, sedikit esensi, dan bahkan itu masuk ke dalam kode.
Dari apa yang ingin saya lakukan, untuk dipikirkan, tetapi tangan saya belum mencapai:- menjalankan bukan hanya satu tetapi beberapa tes secara berurutan dalam satu kali proses
- Saya pikir, memompa entitas sehingga mereka dapat menghasilkan nilai berdasarkan fakta pengujian baru, dan mereka diselamatkan selama eksekusi
- membuat kontrol versi terpusat. Bukan hanya git, tetapi untuk menunjukkan versi tes mana yang harus dijalankan, baik, atau lagi, modul pintar yang memahami versi mana yang relevan, yang belum
- seperti yang saya katakan, untuk memulai tes baru dengan nilai-nilai baru, saya perlu mengubah 1 digit, mengotomatisasi, seolah-olah, membuat modul pintar untuk itu
- meskipun itu tidak mengganggu saya banyak karena saya memiliki semua pelacak disimpan di satu tempat, masih dengan cara yang baik saya harus membuat struktur yang lebih ramah pengguna untuk menyimpannya
- tidak mencoba-coba dengan server selenium. Saya pikir ada baiknya memikirkan hal ini, serta kemungkinan adaptasi lebih lanjut untuk CI, Team City, dll.
Yah, itu saja. Saya lampirkan referensi ke github: kode sumber .Saya akan sangat senang dengan kritik yang membangun, saya harap proyek ini benar-benar bermanfaat.