Dalang dengan ES6 di node dan browser, atau mengapa Zora adalah kerangka uji terbaik di ceruknya

Semuanya baik-baik saja selama Anda perlu menjalankan sumber JS melalui boneka untuk membuat bundel, tetapi neraka dimulai ketika Anda ingin menulis tes untuk situs atau pustaka Anda. Masalahnya adalah bahwa semua kerangka kerja pengujian menggunakan fungsi spesifik dari sebuah simpul dan / atau ditulis dalam ES5. Dengan demikian, meluncurkan tes E2E bukanlah tugas yang sepele dan menawarkan menari dengan rebana dari transpirasi dan sumber daya untuk menutupi kode. Anda tidak ingin kesalahan menunjuk ke tempat yang salah?



Pada artikel ini, saya akan menjelaskan pengalaman saya menggunakan Puppeteer untuk tugas kecil,
dan bagaimana saya meluncurkan modul ES6 di node dan browser, hanya memiliki satu sumber untuk pengujian tanpa pengumpul.


Mengapa Dalang sama sekali, Anda bertanya, mengapa tidak WebDriver? Saya hanya memperhatikan bagaimana pencipta pustaka WebGL open source populer tersiksa, misalnya, mereka memiliki 300 halaman dengan contoh, yang masing-masing dapat diputus dengan komit apa pun. Mereka memeriksanya setelah setiap perubahan, dan jika mereka lupa membuka sesuatu - maaf Β―\_(ツ)_/Β― , itu rusak. Jika belum ada yang memecahkan masalah ini, saya memutuskan untuk mencobanya di lib kecil saya. Pikiran pertama adalah menjalankan tanpa kepala-gl, tetapi itu sudah usang. Node-gles sudah mendukung WebGL2, tetapi bukan ekstensi langka yang saya gunakan. WebDriver? Saya bahkan belum mencobanya. Saya tidak yakin apakah ini mungkin, saya tidak perlu python / C # / Java, tetapi saya membutuhkan JS / TS dengan simpul terbaru dan API peramban terbaru, sehingga fitur terbang dapat berasal dari spesifikasi terbaru.


Mengapa modul ES6? Dukungan untuk WebGL dan ES6 di browser hampir sama. Dan dengan modul bundel atau tidak, biarkan pengguna memutuskan, Anda dapat mengumpulkan kedua versi. Tapi ternyata untuk pengujian unit, sangat nyaman untuk menggunakan versi dengan modul, karena sourcemaps diekstraksi dengan sangat sederhana, dan setelah itu Anda dapat menjalankan tes tanpa ada gerakan tambahan di node atau di browser. Menjalankannya dalam dalang, E2E dengan cakupan kode hampir gratis. Naskah dengan target dalam ES6 mungkin diperlukan, tetapi pada proyek kecil yang ditutupi dengan tes, js normal juga akan berfungsi.


Jadi, cukup perkenalan, saya memasukkan puppeteer dan puppeteer-to-istanbul dalam proyek dan menulis pembungkus seperti itu


 // puppeteer.js import puppeteer from 'puppeteer'; import pup2ist from 'puppeteer-to-istanbul'; (async () => { const browser = await puppeteer.launch({ headless: process.env.HEADLESS, // headless customization slowMo: 250 // good fature for new configs }); const page = (await browser.pages())[0]; // enable coverage await page.coverage.startJSCoverage(); await page.coverage.startCSSCoverage(); // some additional code with console events here... // navigate to unit test page await page.goto('http://127.0.0.1:1234/'); // disable coverage const jsCoverage = await page.coverage.stopJSCoverage(); const cssCoverage = await page.coverage.stopCSSCoverage(); pup2ist.write([...jsCoverage, ...cssCoverage]) await new Promise(resolve => setTimeout(resolve, 6000)); await browser.close(); })(); 

Yang dapat dijalankan dengan node --experimental-modules --no-warnings ./test/puppeteer.js perintah node --experimental-modules --no-warnings ./test/puppeteer.js dengan 11+ node, atau bahkan tanpa flag pada node 13.2+. Tentu saja Anda dapat menggunakan require , lalu ... Tapi mengapa? Ini umumnya backend, di sini dukungan pelanggan bahkan tidak diperlukan! Kode berikut dari package.json memungkinkan kita untuk menyesuaikan pemuatan HEADLESS di konsol dan di cloud CI jika diperlukan pengaturan yang berbeda. Di travs / circle-ci, linux mungkin akan diinstal dan Anda dapat mengatur variabel lingkungan dalam format ini di sana. concurrently membuka dua proses dalam satu konsol secara paralel.


 // package.json { //bla-bla... "type": "module", // this line indicates that we are using es6 modules "scripts": { "test": "node --experimental-modules --no-warnings ./test/puppeteer.js", "server": "http-server -c-1 -p 1234", "not-bad-cmd--dude": "concurrently -k -s first \"npm:test\" \"npm:server\"", "ci": "HEADLESS=true concurrently -k -s first \"npm:test\" \"npm:server\"", } } 

Pada mesin lokal, setelah memasukkan perintah npm run server , npm run server http akan mulai, dan pada npm run test puppeteer npm run test di jendela terpisah, jendela krom. Pada dasarnya itu semua yang perlu Anda ketahui tentang dalang. Contoh lebih lanjut tentang tangkapan layar, emulasi perangkat, area admin, dll. Terdapat di sini . Ngomong-ngomong, bersama dengan paket puppeteer , Anda memasang chrome terpisah di node_modules , jika Anda tidak membutuhkannya, ganti dengan puppeteer-core atau puppeteer-firefox . Perlu dicatat bahwa dalam contoh di atas, kami mendapat cakupan kode JS / CSS gratis yang ditulis dalam folder .nyc_output, hingga kami fokus pada hal ini, pada tahap ini kami tidak kedinginan, tidak panas, tetapi jika ada, itu ada, dan statistik Cakupan tes hampir siap untuk dilihat.



Sekarang mari kita beralih ke tes sendiri, mencoba memilih di mana saya akan menjalankan E2E di lib kecil saya, saya menemukan grafik berikut, yang membandingkan kinerja kerangka kerja untuk pengujian. Mungkin, runtime tidak begitu penting, tetapi ketika beberapa Jest memulai mereka 10 kali lebih lambat, pertanyaan "apa itu dan mengapa itu diperlukan" muncul. Kriteria pemilihan utama menjalankan es6 dengan baris <script type="module" src="./test.js"></script> di halaman html. Karena pada saat menulis kode saya, node belum sepenuhnya mendukung ES6 (kemarin dirilis 12,3 di mana bendera dihapus). Saya memutuskan bahwa jika Anda mengambil kerangka kerja dengan sumber-sumber di TS atau ES6 +, maka itu pasti harus dimulai. Secara umum, Anda mungkin dapat mengambil beberapa jenis moka, mendeklarasikannya lebih tinggi pada halaman dan merujuk ke kelas yang dinyatakan, tetapi apa yang terjadi jika kesalahan terjadi? Secara umum, Anda dapat memberi nama tes pelari favorit Anda di sini. Saya hanya akan mengatakan bahwa Zora mendukung format TAP, dan itu berarti seluruh kebun binatang pemakan TAP cocok untuk itu. Ini memiliki sebagian besar pernyataan, mendukung async, itu adalah salah satu yang tercepat, ditulis dalam ES6 murni tanpa ketergantungan pada node itu sendiri. Bagi saya, itu adalah berlian nyata untuk proyek-proyek kecil.


Akibatnya, saya mendapat beberapa tes yang berfungsi baik di browser dan di node. Dokumentasi Zora memiliki instruksi komprehensif tentang pernyataan dan pengelompokan perintah.


 // test.js import MyLibrary from '../dist/my-library.module.js'; import { test } from 'https://cdn.jsdelivr.net/npm/zora@3.0.3/dist/bundle/module.js'; test('CPU', async (t) => { // some stuff here t.ok(tfps != null, 'fps = ' + (tfps != null ? tfps.toFixed(1) : 'null')); t.ok(tcpu != null, 'cpu = ' + (tcpu != null ? tcpu.toFixed(1) : 'null')); }); test('Memory', async (t) => { // some stuff here t.ok(tmem != null, 'mem = ' + (tmem != null ? tmem.toFixed(1) : 'null')); }); // etc... 

Untuk menunjukkan konsol tanpa rakitan, saya harus membuat sniffer serupa. Konsol telanjang tidak terlalu rapi, mungkin untuk menghubungkan output TAP di suatu tempat untuk memandu maraton. Tetapi lucunya adalah bahwa hasil tes pada klien Anda dapat dilihat secara online . Juga, kode yang sama persis berjalan di CI pada komit apa pun.


 <!DOCTYPE html> <html lang="en"> <head> <!-- some declarations in head --> </head> <body> <!-- some declarations in body --> <script> const addSniffer = (spyTarget) => function() { spyTarget.apply(window.console, arguments); sniffer([...arguments]); } window.console.log = addSniffer(window.console.log); window.console.error = addSniffer(window.console.error); let screen = document.getElementById('screen'); function sniffer(string) { let screen = document.getElementById("screen"); string.forEach(line => { let div = document.createElement("div"); let text = document.createTextNode(line); div.appendChild(text) screen.appendChild(div); }); } </script> <script type="module" src="./test.js"></script> </body> </html> 

Tapi itu tidak semua, dengan tes yang sudah jadi, Anda dapat menghubungkan bot seperti merenovasi / greenkeeper / dependabot, yang akan memperbarui dependensi di perpustakaan Anda, dan melakukan komitmen otomatis, setelah memeriksa kebenaran pembaruan. Dan travis / github-ci / circle-ci akan mengunggah versi baru paket npm.


Sebagai contoh, konfigurasi seperti dari renovasi, membuat otomatis melakukan pada hari Minggu, dan menaikkan versinya


 { "automerge": true, "automergeType": "branch", "bumpVersion": "patch", "schedule": ["on sunday"], "ignorePaths": [".circleci"] } 

Dan travis, ketika Anda sendiri mengangkat versi atau bot tertentu, dapat secara otomatis mengunggah paket ke npm. Untuk melakukan ini, buat akun di travis-ci.org , aktifkan f2a seperti yang dijelaskan dalam artikel ini , masukkan dua kunci rahasia $NPM_EMAIL dan $NPM_TOKEN , dan buat konfigurasi serupa.


 language: node_js node_js: '12' script: - npm run ci deploy: provider: npm edge: true email: $NPM_EMAIL api_key: $NPM_TOKEN on: branch: master 

Secara total, itu mungkin terjadi, tetapi sulit untuk menghilangkan pemberitahuan dari github bahwa kerentanan muncul dalam beberapa jenis ketergantungan: D

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


All Articles