Puppeteer مع ES6 في عقدة ومتصفح ، أو لماذا تعتبر Zora أفضل إطار اختبار في مكانه

كل شيء على ما يرام طالما كنت بحاجة إلى تشغيل مصادر JS عبر الدمى لإنشاء حزمة ، ولكن يبدأ الجحيم عندما تريد كتابة اختبارات لموقعك أو مكتبتك. المشكلة هي أن جميع أطر الاختبار تستخدم وظائف محددة من عقدة و / أو مكتوبة في ES5. وبالتالي ، فإن إجراء اختبارات E2E ليس مهمة تافهة ويوفر الرقص مع الدف من عمليات النقل وخرائط المصدر لتغطية الشفرة. لا تريد أن تشير الأخطاء إلى المكان الخطأ؟



في هذه المقالة ، سوف أصف تجربتي في استخدام Puppeteer لمهمة صغيرة ،
وكيف أطلقت وحدات ES6 في العقدة والمتصفح ، مع وجود مصدر واحد فقط للاختبارات بدون جامعين.


لماذا Puppeteer على الإطلاق ، تسأل ، لماذا لا WebDriver؟ لقد لاحظت للتو كيف يتم تعذيب منشئي مكتبات WebGL الشعبية المفتوحة المصدر ، على سبيل المثال ، لديهم 300 صفحة مع أمثلة ، يمكن لكل منها أن ينفصل عن أي التزام. يقومون بفحصها بعد كل تغيير ، وإذا نسوا فتح شيء ما - آسف ¯\_(ツ)_/¯ ، فقد انهار. إذا لم يقم أحد بحل هذه المشكلة بعد ، فقد قررت تجربتها أثناء ربي الصغير. كانت الفكرة الأولى هي الركض بلا رأس ، لكنها عفا عليها الزمن. يدعم Node-gles بالفعل WebGL2 ، ولكن ليس الامتداد النادر الذي استخدمته. WebDriver؟ لم أجربها حتى. لست متأكدًا مما إذا كان هذا ممكنًا ، فلم أكن بحاجة إلى python / C # / Java ، لكنني كنت بحاجة إلى JS / TS مع أحدث العقدة وأحدث واجهة برمجة تطبيقات للمتصفح ، لذلك يمكن أن تكون ميزات الطيران من أحدث المواصفات.


لماذا هي وحدات ES6؟ دعم WebGL و ES6 في المتصفحات هو نفسه تقريبا. ومع وحدات الحزمة أو لا ، دع المستخدم يقرر ، يمكنك ببساطة جمع كلا الإصدارين. ولكن اتضح فيما يتعلق باختبار الوحدة ، من المريح جدًا استخدام الإصدار مع الوحدات النمطية ، حيث يتم استخراج خرائط المصدر ببساطة شديدة ، ويمكن تشغيل الاختبارات دون أي لفتات إضافية في العقدة أو في المستعرض. تشغيلها في دمية ، E2E مع تغطية رمز مجاني تقريبا. ربما كانت هناك حاجة إلى برنامج نصي يحتوي على هدف في ES6 ، ولكن في مشروع صغير مغطى بالاختبارات ، ستعمل أيضًا js العادية.


لذلك ، بما فيه الكفاية مقدمات ، وضعت puppeteer puppeteer-to-istanbul في المشروع وكتبت مثل هذا المجمع


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

والتي يمكن تشغيلها باستخدام node --experimental-modules --no-warnings ./test/puppeteer.js الأوامر node --experimental-modules --no-warnings ./test/puppeteer.js مع عقدة 11+ ، أو حتى بدون إشارات على العقدة 13.2+. بالطبع يمكنك استخدام require ، ثم ... ولكن لماذا؟ هذا هو عموما خلفية ، هنا ليست هناك حاجة حتى دعم العملاء! يسمح لنا التعليمة البرمجية التالية من package.json بتخصيص تنزيلات HEADLESS في وحدة التحكم وفي سحابة CI إذا كانت هناك حاجة لإعدادات مختلفة لها. في travs / circle-ci ، من المحتمل أن يتم تثبيت linux ويمكنك تعيين متغيرات البيئة بهذا التنسيق هناك. concurrently يفتح عمليتين في وحدة واحدة بالتوازي.


 // 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\"", } } 

على الجهاز المحلي ، بعد إدخال أمر npm run server ، سيبدأ npm run server http ، ويقوم npm run test الدمى في نافذة منفصلة ، نافذة الكروم. هذا هو كل ما تحتاج إلى معرفته عن العرائس. توجد هنا أمثلة أخرى على لقطات الشاشة ومحاكاة الأجهزة ومسؤولي الإدارة وما إلى ذلك. بالمناسبة ، جنبًا إلى جنب مع حزمة puppeteer ، قمت بتثبيت chrome منفصل في node_modules ، إذا لم تكن في حاجة إليها ، node_modules بـ puppeteer-core أو puppeteer-firefox . تجدر الإشارة إلى أنه في المثال أعلاه ، حصلنا على تغطية برمجية JS / CSS مجانية مكتوبة في مجلد .nyc_output ، حتى نركز على ذلك ، في هذه المرحلة ، لن نشعر بالبرد ، ليس حارًا ، لكن إذا كان هناك أي شيء ، فهو موجود والإحصائيات تغطية الاختبار جاهزة تقريبًا للعرض.



الآن دعنا ننتقل إلى الاختبارات نفسها ، في محاولة لاختيار المكان الذي سأقوم بتشغيل E2E به في بلدي الصغير ، صادفت الرسوم البيانية التالية ، التي قارنت أداء أطر العمل للاختبار. ربما ، لا يكون وقت التشغيل مهمًا للغاية ، لكن عندما يبدأ بعض Jest في تشغيله بمعدل 10 مرات أبطأ ، يطرح السؤال "ما هو ولماذا يحتاج". تم تشغيل معيار الاختيار الرئيسي es6 مع السطر <script type="module" src="./test.js"></script> في صفحة html. منذ وقت كتابة الكود ، لم تدعم العقدة ES6 بشكل كامل (تم إصدارها بالأمس 12.3 حيث تمت إزالة الأعلام). قررت أنه إذا كنت تأخذ الإطار مع المصادر على TS أو ES6 + ، فمن المؤكد أنه يجب أن يبدأ. بشكل عام ، من المحتمل أن تأخذ نوعًا من المخاوي ، وتعلنه أعلى على الصفحة وتشير إلى الفئة المعلنة ، لكن ماذا يحدث إذا حدث خطأ؟ بشكل عام ، يمكنك تسمية اختبار العداء المفضل لديك هنا. سأقول فقط أن Zora يدعم تنسيق TAP ، وهذا يعني أن حديقة حيوانات كاملة من أكلة TAP مناسبة لها. يحتوي على معظم التأكيدات ، ويدعم المزامنة ، وهو واحد من الأسرع ، المكتوب في ES6 النقي دون تبعية على العقدة نفسها. بدا لي أنه ماسة حقيقية للمشاريع الصغيرة.


نتيجة لذلك ، حصلت على بعض الاختبارات التي تعمل في المستعرض وفي العقدة. تحتوي وثائق Zora على إرشادات شاملة حول التأكيدات وتجمعات الأوامر.


 // 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... 

من أجل إظهار وحدة التحكم دون تجميعات ، اضطررت إلى صنع متشمم مماثل. وحدة التحكم العارية ليست جيدة جدًا ، يمكنك توصيل خرج TAP في مكان ما لتوجيه الماراثون. ولكن الشيء المضحك هو أنه يمكن عرض نتائج الاختبار على عميلك عبر الإنترنت . أيضا ، بالضبط نفس الرمز يعمل في CI على أي التزام.


 <!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> 

ولكن هذا ليس كل شيء ، من خلال الاختبارات الجاهزة ، يمكنك توصيل برامج الروبوتات مثل repair / greenkeeper / dependabot ، والتي من شأنها تحديث التبعيات في مكتبتك ، والقيام بالالتزامات التلقائية ، بعد التحقق من صحة التحديثات. وكان travis / github-ci / circle-ci قد حمّل نسخة جديدة من حزم npm.


على سبيل المثال ، مثل هذا التكوين من التجديد ، يجعل الإلتزام التلقائي في أيام الأحد ، ويرفع الإصدار


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

و travis ، عندما تقوم أنت بنفسك برفع الإصدار أو بعض برامج الروبوت ، يمكن تحميل الحزمة تلقائيًا إلى npm. للقيام بذلك ، قم بإنشاء حساب على travis-ci.org ، travis-ci.org بتمكين f2a كما هو موضح في هذه المقالة ، وأدخل مفتاحين سريين $NPM_EMAIL و $NPM_TOKEN ، وقم بإنشاء تهيئة مماثلة.


 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 

بشكل إجمالي ، يكون ذلك ممكنًا بطريقة ما ، لكن من الصعب التخلص من الإشعارات من github بأن هناك ثغرة أمنية تظهر في نوع من التبعية: D

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


All Articles