Kami menggunakan otomatisasi dalam beberapa jam: TypeScript, Protractor, Jasmine

Halo, Habr!

Nama saya Vitaliy Kotov, saya melakukan banyak pengujian otomasi dan saya menyukainya. Saya baru-baru ini berpartisipasi dalam sebuah proyek untuk mengkonfigurasi otomatisasi dari awal pada tumpukan TypeScript + Protractor + Jasmine. Bagi saya, tumpukan ini baru dan saya mencari informasi yang diperlukan di Internet.

Saya berhasil menemukan manual yang paling berguna dan masuk akal hanya dalam bahasa Inggris. Saya memutuskan bahwa dalam bahasa Rusia saya juga perlu melakukan ini. Saya hanya akan memberi tahu Anda dasar-dasarnya: mengapa tumpukan itu, apa yang perlu Anda konfigurasi, dan seperti apa tes paling sederhana.

Saya harus segera mengatakan bahwa saya jarang bekerja dengan NodeJS, npm, dan dengan JavaScript sisi server secara umum (terutama dengan TypeScript). Jika Anda menemukan kesalahan dalam terminologi di suatu tempat atau beberapa keputusan saya dapat diperbaiki, saya akan senang mengetahuinya dalam komentar dari orang-orang yang lebih berpengalaman.

Ngomong-ngomong, saya sudah memiliki artikel serupa: "Kami menggunakan otomatisasi dalam beberapa jam: PHPUnit, Selenium, Composer" .



Tantangan


Pertama-tama, mari kita cari tahu masalah apa yang sedang kita pecahkan. Kami memiliki aplikasi web yang ditulis menggunakan AngularJS. Ini adalah kerangka kerja JavaScript berdasarkan proyek web mana yang sering ditulis.

Dalam artikel ini, kami tidak akan mempertimbangkan pro dan kontra dari proyek AngularJS. Hanya beberapa kata tentang fitur proyek semacam itu dalam hal menulis tes e2e untuk mereka.

Aspek yang agak penting dari otomatisasi pengujian adalah bekerja dengan elemen halaman, yang terjadi dengan bantuan pencari lokasi. Locator adalah garis yang disusun berdasarkan aturan tertentu dan mengidentifikasi elemen UI: satu atau lebih.

Untuk web, CSS dan Xpath paling sering digunakan. Terkadang, jika ada elemen dengan ID unik di halaman tersebut, Anda dapat mencarinya. Namun, bagi saya sepertinya WebDriver masih mengubah ID ini menjadi pencari lokasi CSS pada akhirnya dan sudah bekerja dengannya.

Jika kita melihat kode HTML beberapa proyek AngularJS, kita akan melihat banyak atribut untuk elemen yang tidak ada dalam HTML klasik:



Kode diambil dari halaman demo-busur derajat .

Semua atribut yang dimulai dengan ng- * digunakan oleh AngularJS untuk bekerja dengan UI. Situasi yang cukup khas adalah ketika elemen selain atribut kontrol ini tidak memiliki yang lain, yang memperumit proses kompilasi pencari kualitas.

Mereka yang telah melakukan banyak otomasi tahu tentang nilai UI semacam itu yang dapat dengan mudah ditemukan oleh pencari. Bagaimanapun, ini jarang terjadi untuk proyek-proyek besar. :)

Sebenarnya, untuk proyek semacam itu, kita juga perlu mengonfigurasi otomatisasi uji. Ayo pergi!

Apa itu apa?


Pertama-tama, mari kita cari tahu mengapa setiap komponen tumpukan kita diperlukan.

Busur derajat adalah kerangka uji yang didasarkan pada WebDriverJS. Dialah yang akan meluncurkan browser kami, membuat mereka membuka halaman yang diperlukan dan berinteraksi dengan elemen yang diperlukan.

Kerangka kerja ini secara khusus dirancang untuk proyek AngularJS. Ini memberikan cara tambahan untuk menentukan lokasi:

element(by.model('first')); element(by.binding('latest')); element(by.repeater('some')); 

Daftar lengkap dapat ditemukan di halaman manual .

Metode-metode ini menyederhanakan pembuatan dan dukungan pelacak pada suatu proyek. Namun, Anda harus memahami bahwa "di bawah tenda" semua ini dalam kasus apa pun dikonversi ke css. Faktanya adalah bahwa protokol W3C, atas dasar di mana interaksi di WebDriver berlangsung, hanya dapat bekerja dengan satu set locator yang terbatas. Daftar ini dapat dilihat di w3.org .

TypeScript adalah bahasa pemrograman yang dibuat oleh Microsoft. TypeScript berbeda dari JavaScript dalam kemampuan mengetik variabel, dukungan untuk penggunaan kelas penuh dan kemampuan untuk menghubungkan modul.

Ditulis dalam kode TS untuk bekerja dengan mesin V8 diterjemahkan ke dalam kode JS, yang sudah dieksekusi. Selama transformasi ini, kode diperiksa untuk kepatuhan. Sebagai contoh, itu tidak "mengkompilasi" jika, bukannya int, string secara eksplisit diteruskan ke fungsi di suatu tempat.

Jasmine adalah kerangka kerja untuk menguji kode JavaScript. Bahkan, itu berkat dia bahwa kode JS kita berubah menjadi apa yang kita sebut tes. Dia mengelola tes ini.

Di bawah ini kita melihat kemampuannya.

Pengaturan perakitan dan proyek


Nah, kami memutuskan satu set kerangka kerja, sekarang mari kita selesaikan semua ini.

Untuk bekerja dengan kode, saya memilih Visual Studio Code dari Microsoft. Meskipun banyak yang menulis di WebStorm atau bahkan Intellij Idea dari JetBrains.

Saya sudah menginstal NodeJS (v11.6.0) dan NPM (6.9.0). Jika Anda tidak memilikinya, ini bukan masalah, menginstalnya tidak akan sulit. Semuanya dijelaskan secara cukup rinci di situs web resmi .

Benang dapat digunakan sebagai pengganti NPM, meskipun ini tidak penting untuk proyek kecil.

Dalam IDE kami, kami membuat proyek baru. Kami membuat package.json di root proyek - di dalamnya kami akan menjelaskan semua paket yang kami butuhkan untuk proyek tersebut.

Anda dapat membuatnya menggunakan perintah npm init . Atau Anda cukup menyalin konten ke file.

Awalnya, package.json terlihat seperti ini:

 { "name": "protractor", "dependencies": { "@types/node": "^10.5.2", "@types/jasmine": "^3.3.12", "protractor": "^5.4.2", "typescript": "^3.4.1" } } 

Setelah itu kami menjalankan perintah install npm untuk menginstal semua modul yang diperlukan dan dependensinya (yah, Anda ingat gambar yang sangat jelas tentang sesuatu yang lebih berat daripada black hole ...)

Sebagai hasilnya, kita harus memiliki direktori node_modules. Jika dia muncul, maka semuanya berjalan sesuai rencana. Jika tidak, ada baiknya melihat ke hasil eksekusi perintah, biasanya semuanya dijelaskan secara cukup rinci di sana.

TypeScript dan konfigurasinya


Untuk menginstal TypeScript, kita perlu npm:

 npm install -g typescript 

Pastikan sudah terpasang:

 $ tsc -v Version 3.4.1 

Segalanya tampak teratur.

Sekarang kita perlu membuat konfigurasi untuk bekerja dengan TS. Itu juga harus di root proyek dan disebut tsconfig.json

Isinya akan seperti ini:

 { "compilerOptions": { "lib": ["es6"], "strict": true, "outDir" : "output_js", "types" : ["jasmine", "node"] }, "exclude": [ "node_modules/*" ] } 

Singkatnya, kami menentukan yang berikut ini dalam konfigurasi ini:

  • Di mana direktori untuk meletakkan JS-code terakhir (dalam kasus kami ini adalah output_js)
  • Aktifkan mode ketat
  • Diindikasikan dengan kerangka kerja mana kami bekerja
  • Node_modules dikecualikan dari kompilasi

TS memiliki beragam pengaturan. Ini cukup untuk proyek kami. Anda dapat mempelajari lebih lanjut di typescriptlang.org .

Sekarang mari kita lihat bagaimana perintah tsc bekerja , yang akan mengubah kode TS kita menjadi kode JS. Untuk melakukan ini, buat file check_tsc.ts sederhana dengan konten berikut:

 saySomething("Hello, world!"); function saySomething(message: string) { console.log(message); } 

Dan kemudian jalankan perintah tsc (untuk ini Anda harus berada di dalam direktori proyek).

Kita akan melihat bahwa kita memiliki direktori output_js dan file js yang serupa dengan konten berikut telah muncul di dalamnya:

 "use strict"; saySomething("Hello, world!"); function saySomething(message) { console.log(message); } 

File ini sudah dapat diluncurkan menggunakan perintah node:

 $ node output_js/check_tsc.js Hello, world! 

Jadi, kami menulis program TypeScipt pertama kami, selamat. Mari kita menulis tes sekarang. :)

Konfigurasi busur derajat


Untuk busur derajat kita juga membutuhkan konfigurasi. Tapi itu tidak akan lagi dalam bentuk json, tetapi dalam bentuk file-ts. Sebut saja config.ts dan tulis kode berikut di sana:

 import { Config } from "protractor"; export const config: Config = { seleniumAddress: "http://127.0.0.1:4444/wd/hub", SELENIUM_PROMISE_MANAGER: false, capabilities: { browserName: "chrome", /*chromeOptions: { args: [ "--headless", "--window-size=800,600" ] }*/ }, specs: [ "Tests/*Test.js", ] }; 

Dalam file ini kami menentukan yang berikut:

Pertama, jalur ke server Selenium yang sedang berjalan. Ini cukup sederhana untuk dijalankan, Anda hanya perlu mengunduh file jar Standalone Server dan driver yang diperlukan (misalnya, driver chrome untuk browser Chrome ). Selanjutnya, tulis perintah berikut:

 java -jar -Dwebdriver.chrome.driver=/path/to/chromedriver /path/to/selenium-server-standalone.jar 

Sebagai hasilnya, kita harus melihat kesimpulan berikut:

 23:52:41.691 INFO [GridLauncherV3.launch] - Selenium build info: version: '3.11.0', revision: 'e59cfb3' 23:52:41.693 INFO [GridLauncherV3$1.launch] - Launching a standalone Selenium Server on port 4444 2019-05-02 23:52:41.860:INFO::main: Logging initialized @555ms to org.seleniumhq.jetty9.util.log.StdErrLog 23:52:42.149 INFO [SeleniumServer.boot] - Welcome to Selenium for Workgroups.... 23:52:42.149 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444 

Port 4444 default. Itu dapat diatur menggunakan parameter -port atau melalui parameter konfigurasi "seleniumArgs" => "-port".

Jika Anda ingin lebih mudah dan lebih cepat: Anda dapat mengunduh npm paket webdriver-manager .

Dan kemudian mengelola server menggunakan perintah start, shutdown, dan sebagainya. Tidak banyak perbedaan, hanya saja saya lebih terbiasa bekerja dengan file jar. :)

Kedua , kami mengindikasikan bahwa kami tidak ingin menggunakan manajer Janji. Lebih lanjut tentang ini nanti.

Ketiga , kami menentukan kemampuan untuk browser kami. Saya berkomentar sebagian, misalnya, bahwa kita dapat dengan mudah meluncurkan browser dalam mode tanpa kepala. Ini adalah fitur keren, tetapi itu tidak akan memungkinkan Anda untuk mengamati tes kami secara visual. Sementara itu, kami baru belajar - saya ingin. :)

Keempat , kami menetapkan topeng untuk spesifikasi (tes). Segala sesuatu yang ada di folder Tes dan berakhir dengan Test.js. Kenapa di js, bukan ts? Ini karena pada akhirnya, Node akan bekerja secara khusus dengan file JS, dan bukan dengan file TS. Penting untuk tidak bingung, terutama pada awal pekerjaan.

Sekarang buat folder Tes dan tulis tes pertama. Dia akan melakukan hal berikut:

  • Menonaktifkan memeriksa bahwa ini adalah halaman Angular. Tanpa ini, kami mendapatkan pesan kesalahan ini: Kesalahan saat menjalankan testForAngular. Tentu saja, untuk halaman Angular cek ini tidak perlu dimatikan.
  • Pergi ke halaman Google.
  • Periksa apakah ada bidang input teks.
  • Masukkan teks "busur derajat".
  • Klik tombol kirim (ini memiliki pelacak yang agak rumit, karena ada dua tombol dan yang pertama tidak terlihat).
  • Diharapkan bahwa URL akan berisi kata "busur derajat" - ini berarti bahwa kami melakukan segalanya dengan benar dan pencarian dimulai.

Ini kode yang saya dapat:

 import { browser, by, element, protractor } from "protractor"; describe('Search', () => { it('Open google and find a text', async () => { //       let EC = protractor.ExpectedConditions; //    AngularJS await browser.waitForAngularEnabled(false); //   Google await browser.get('https://www.google.com/'); //    css = input[role='combobox'] let input_button = element(by.css("input[role='combobox']")); //     ( presenceOf) await browser.wait(EC.presenceOf(input_button), 5000); //     “protractor” await input_button.sendKeys("protractor"); //      css let submit_button = element(by.css(".FPdoLc input[type='submit'][name='btnK']")); //      ( ,     input-,   ) await browser.wait(EC.presenceOf(submit_button), 5000); //     await submit_button.click(); // ,  URL    'protractor' await browser.wait(EC.urlContains('protractor'), 5000); }); }); 

Dalam kode, kita melihat bahwa semuanya dimulai dengan fungsi uraikan (). Dia datang kepada kami dari kerangka Jasmine. Ini adalah pembungkus untuk skrip kami. Di dalamnya, mungkin ada fungsi beforeAll () dan beforeEach () untuk melakukan manipulasi sebelum semua tes dan sebelum setiap tes. Sebanyak fungsi yang ada () sebenarnya adalah pengujian kami. Pada akhirnya, jika didefinisikan, afterAll () dan afterEach () akan dieksekusi untuk manipulasi setelah setiap tes dan semua tes.

Saya tidak akan berbicara tentang semua fitur Jasmine, Anda dapat membacanya di situs web jasmine.imtqy.com

Untuk menjalankan pengujian kami, pertama-tama Anda perlu mengubah kode TS menjadi kode JS, dan kemudian jalankan:

 $ tsc $ protractor output_js/config.js 

Tes kami dimulai - kami hebat. :)



Jika tes tidak dimulai, ada baiknya memeriksa:

  • Bahwa kodenya ditulis dengan benar. Secara umum, jika ada kesalahan kritis dalam kode, kami akan menangkapnya selama perintah tsc.
  • Server Selenium itu sedang berjalan. Untuk melakukan ini, Anda dapat membuka URL http: //127.0.0.1-00-00444/wd/hub - harus ada antarmuka untuk sesi-sesi Selenium.
  • Chrome itu dimulai secara normal dengan versi driver-chrome yang diunduh. Untuk melakukan ini, pada halaman / hub / halaman, klik Buat Sesi dan pilih Chrome. Jika tidak dimulai, maka Anda perlu memperbarui Chrome, atau mengunduh versi lain dari driver chrome.
  • Jika semua ini gagal, Anda dapat memverifikasi bahwa perintah instal npm telah berhasil diselesaikan.
  • Jika semuanya ditulis dengan benar, tetapi tetap saja tidak ada yang dimulai - cobalah untuk mencari kesalahan di google. Ini paling sering membantu. :)

Skrip NPM


Untuk membuat hidup lebih mudah, Anda dapat membuat bagian dari perintah npm alias. Sebagai contoh, saya ingin menghapus direktori dengan file JS sebelumnya dan membuatnya kembali dengan yang baru sebelum setiap tes dijalankan.

Untuk melakukan ini, tambahkan item skrip ke package.json:

 { "name": "protractor", "scripts": { "test": "rm -rf output_js/; tsc; protractor output_js/config.js" }, "dependencies": { "@types/node": "^10.5.2", "@types/jasmine": "^3.3.12", "protractor": "^5.4.2", "typescript": "^3.4.1" } } 

Sekarang memasukkan perintah tes npm , berikut ini akan terjadi: direktori output_js dengan kode lama akan dihapus, itu akan dibuat lagi dan kode JS baru akan ditulis untuk itu. Setelah itu tes akan segera dimulai.

Alih-alih serangkaian perintah ini, Anda dapat menentukan perintah lain yang Anda perlukan untuk bekerja. Misalnya, Anda dapat memulai dan memadamkan server selenium di antara uji coba. Meskipun ini, tentu saja, lebih mudah untuk mengontrol di dalam kode uji itu sendiri.

Sedikit tentang Janji


Pada akhirnya, saya akan berbicara sedikit tentang Promise, async / menunggu dan bagaimana penulisan tes di NodeJS berbeda dari Java atau Python yang sama.

JavaScript adalah bahasa yang tidak sinkron. Ini berarti bahwa kode tidak selalu dieksekusi sesuai urutan penulisan. Ini termasuk permintaan HTTP, dan kami ingat bahwa kode itu berkomunikasi dengan Selenium Server melalui HTTP.

Janji (biasanya disebut "janji") menyediakan cara mudah untuk mengatur kode asinkron. Anda dapat membaca lebih lanjut tentang mereka di learn.javascript.ru .

Bahkan, ini adalah objek yang membuat satu kode bergantung pada eksekusi kode lainnya, sehingga menjamin urutan tertentu. Busur derajat bekerja sangat aktif dengan benda-benda ini.

Mari kita lihat sebuah contoh. Misalkan kita menjalankan kode berikut:

 driver.findElement().getText(); 

Di Jawa, kami mengharapkan kami mengembalikan objek bertipe String. Dalam busur derajat, ini tidak begitu, kami akan mengembalikan objek Janji. Dan seperti itu, mencetaknya dengan tujuan debug tidak akan berfungsi.

Biasanya kita tidak perlu mencetak nilai yang dihasilkan. Kita perlu meneruskannya ke beberapa metode lain yang sudah bekerja dengan nilai ini. Misalnya, itu akan memeriksa teks untuk kepatuhan dengan yang diharapkan.

Metode serupa di busur derajat juga menerima benda-benda Janji sebagai input, sehingga tidak ada masalah. Tetapi, jika Anda masih ingin melihat nilainya, maka () akan berguna.

Ini adalah bagaimana kami dapat mencetak teks tombol pada halaman Google (perhatikan bahwa karena ini adalah tombol, teks berada di dalam atribut nilai):

 //   let submit_button = element(by.css(".FPdoLc input[type='submit'][name='btnK']")); //    await browser.wait(EC.presenceOf(submit_button), 5000); //   then()   await submit_button.getAttribute("value").then((text) => { console.log(text); }); 

Adapun kata kunci async / menunggu, ini adalah pendekatan yang sedikit lebih baru untuk bekerja dengan kode asinkron. Ini memungkinkan Anda untuk menghindari neraka janji, yang sebelumnya terbentuk dalam kode karena banyaknya jumlah sarang. Namun demikian, Anda tidak akan dapat sepenuhnya menyingkirkan Janji dan Anda harus dapat bekerja dengan mereka. Ini dapat dimengerti dan terperinci dapat ditemukan di artikel Desain async / tunggu dalam JavaScript: kekuatan, perangkap dan fitur penggunaan .

PR


Sebagai pekerjaan rumah, saya sarankan menulis tes untuk halaman yang ditulis dalam AngularJS: protractor-demo .

Jangan lupa untuk menghapus baris dari kode tentang mematikan halaman yang memeriksa AngularJS. Dan pastikan untuk bekerja dengan pencari lokasi yang dirancang khusus untuk AngularJS. Tidak ada keajaiban khusus dalam hal ini, tetapi itu cukup nyaman.

Ringkasan


Mari kita ambil stok. Kami berhasil menulis tes yang berfungsi pada sekelompok TypeScript + Protractor + Jasmine. Kami belajar bagaimana membangun proyek seperti itu, membuat konfigurasi yang diperlukan, dan menulis tes pertama.

Sepanjang jalan, kami membahas sedikit tentang bekerja dengan JavaScript auto-test. Sepertinya bagus untuk beberapa jam. :)

Apa yang harus dibaca, ke mana harus mencari


Protractor memiliki manual yang cukup bagus dengan contoh JavaScript: https://www.protractortest.org/#/tutorial
Jasmine memiliki manual: https://jasmine.imtqy.com/pages/docs_home.html
TypeScipt telah memulai dengan baik: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html

Di Media, ada artikel bagus dalam bahasa Inggris tentang TypeScript + Protractor + Mentimun: https://medium.com/@igniteram/e2e-testing-with-protractor-cucumber-using-typescript-564575814e4a

Dan di repositori saya, saya memposting kode final dari apa yang kita bahas dalam artikel ini: https://github.com/KotovVitaliy/HarbProtractorJasmineJasmine .

Di Internet, Anda dapat menemukan contoh proyek yang lebih kompleks dan lebih besar di tumpukan ini.

Terima kasih atas perhatian anda! :)

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


All Articles