在节点和浏览器中具有ES6的Puppeteer,或者Zora是其利基市场中最佳的测试框架的原因

一切都很好,只要您需要通过虚拟实例运行JS源来创建捆绑包,但是当您想为您的站点或库编写测试时,地狱就开始了。 问题在于所有测试框架都使用节点中的特定功能和/或以ES5编写。 因此,启动E2E测试不再是一项琐碎的任务,它可以用转鼓和源图的手鼓跳舞来覆盖代码。 您不希望错误指向错误的地方吗?



在本文中,我将介绍我使用Puppeteer进行小任务的经验,
以及我如何在节点和浏览器中启动ES6模块,而只有一个测试源没有收集器。


您问为什么根本没有Puppeteer,为什么没有WebDriver? 我刚刚注意到流行的开放源WebGL库的创建者是如何受折磨的,例如,他们有300个页面以及示例,每个页面都可以随任何提交而中断。 他们在每次更改后都会对其进行检查,如果他们忘记打开某些东西了-对不起¯\_(ツ)_/¯ ,它就坏了。 如果还没有人解决这个问题,我决定在我的小图书馆里尝试一下。 最初的想法是运行headless-gl,但是它已经过时了。 Node-gles已经支持WebGL2,但不支持我使用的罕见扩展。 WebDriver? 我什至没有尝试过。 我不确定是否可行,我不需要python / C#/ Java,但是我需要具有最新节点和最新浏览器API的JS / TS,因此可以在最新规范中使用飞行功能。


为什么是ES6模块? 浏览器对WebGL和ES6的支持大致相同。 不管是否使用捆绑软件模块,让用户决定,您都可以简单地收集两个版本。 但是事实证明,对于单元测试而言,将版本与模块一起使用非常方便,因为源映射的提取非常简单,然后您可以在节点或浏览器中运行而无需任何额外手势。 在伪造者中运行它们,具有代码覆盖率的E2E几乎是免费的。 在ES6中可能需要带有目标的Typescript,但是在一个包含测试的小型项目中,正常的js也可以使用。


因此,足够的介绍,我在项目中加入了puppeteerpuppeteer-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 (具有11+节点,甚至在节点13.2+上没有标志)运行。 当然,您可以使用require ,但是...为什么呢? 通常这是一个后端,这里甚至不需要客户支持! package.json的以下代码允许我们在控制台和CI云中自定义HEADLESS下载(如果需要不同的设置)。 在travs / circle-ci中,可能会安装linux,您可以在此处以这种格式设置环境变量。 concurrently在一个控制台中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命令后,http npm run server将启动,在npm run test ,在单独的窗口(chrome窗口)中npm run test puppeteer。 这基本上是您需要知道的关于木偶戏的全部内容。 屏幕截图,设备仿真,管理区域等的更多示例位于此处 。 顺便说一句,连同node_modules软件包一起,您在node_modules安装了一个单独的chrome,如果不需要,则将其替换为node_modules puppeteer-corepuppeteer-firefox 。 应当注意,在上面的示例中,我们获得了免费的JS / CSS代码覆盖率,该覆盖率写在.nyc_output文件夹中,直到我们专注于此为止,在此阶段,我们并不冷,也不热,但如果有的话,就在那里测试覆盖率几乎可以查看了。



现在让我们继续测试本身,尝试选择在小型lib库中运行E2E的位置,我遇到了以下图表,它们比较了测试框架的性能。 可能,运行时不是那么重要,但是当某个Jest启动它们的速度慢10倍时,就会出现“它是什么以及为什么需要它”的问题。 主要选择条件是在html页面中使用<script type="module" src="./test.js"></script>行运行es6。 由于在编写我的代码时,该节点尚未完全支持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> 

但这还不是全部,通过现成的测试,您可以连接诸如renovate / greenkeeper / dependabot之类的机器人,这些机器人将在检查更新的正确性之后更新库中的依赖项并执行自动提交。 travis / github-ci / circle-ci将会上传新版本的npm软件包。


例如,这样的配置来自装修,在星期日进行自动提交,并提高版本


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

而travis,当您自己提出版本或某些bot时,可以自动将软件包上传到npm。 为此,请在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/zh-CN466551/


All Articles