2017年1月9号微信小程序正式上线,小程序不须要安装就能使用,依托微信强大的生态环境,能作到不少H5所不能作的事情。从微信小程序发布这段时间,陆陆续续开发了很多小程序相关的项目,总结了一些通用性的组件,可是对于小程序如何作测试,依然是一头雾水,直到作了很多的项目,积累的一些经验和开源库以后才理清如何作测试,下面将会介绍如何对小程序作UI测试和单元测试。javascript
node
这个应该不用多作介绍了,不过此次demo中要求node版本应该大于7.6.0,由于puppeteer要求最低版本是v6.4.0,可是由于官方示例中大量使用 async/await 等新特性,因此须要使用 v7.6.0 或更高版本的 Node,async/await能让异步回调代码更加简洁,否则整个代码都是promise.then
前端
puppeteer
Chrome 团队出品的一款更友好的Headless Chrome Node API,用于代替用户在页面上面点击、拖拽、输入等多种操做,常见的使用场景仍是应用到UI自动化测试,puppeteer能够对页面进行截图保存为图片或者PDF,解决爬虫没法实现的一些操做(异步加载页面内容) 。java
相似的工具:
phantomjs
seleniumhq
nightmarenode
wept
wept可让小程序脱离开发者工具或者微信客户端直接运行在浏览器上面,后台使用node,提供小程序API的模拟返回(wx.login、wx.getUserInfo等),前端实现了 view 层、service 层和控制层之间的相关通信逻辑。git
mocha
JavaScript测试框架,在浏览器和Node环境均可以使用,经过测试框架,能够为你的JavaScript代码添加相应的测试用例,使得项目代码更增强健。github
chai
Chai是一个BDD/TDD模式的断言库,在node和浏览器环境都能运行,API通俗易懂,断言类型和方式丰富,搭配mocha,江湖人戏称为"抹茶"chrome
npm i -g wept
npm i --save-dev puppeteer mocha chainpm
在安装puppeteer有可能会出现如下报错小程序
ERROR: Failed to download Chromium r508693! Set "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" env variable to skip download. Error: Download failed: server returned code 502. URL: https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/508693/chrome-win32.zip at ClientRequest.https.get.response (D:\chromium\node_modules\puppeteer\utils\ChromiumDownloader.js:197:21) at Object.onceWrapper (events.js:316:30) at emitOne (events.js:115:13) at ClientRequest.emit (events.js:210:7) at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:565:21) at HTTPParser.parserOnHeadersComplete (_http_common.js:116:23) at Socket.socketOnData (_http_client.js:454:20) at emitOne (events.js:115:13) at Socket.emit (events.js:210:7) at ClientRequest.onsocket (D:\chromium\node_modules\https-proxy-agent\index.js:181:14)
实际上是由于下载完puppeteer包以后有执行node install.js
去下载chromium(实验版chrome),可是因为网络的缘由,下载失败了,咱们能够避免缺省的下载 chromium,经过设置环境变量来阻止set PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
而后手动去下载chromium,上面有给出连接https://storage.googleapis.co...微信小程序
直接看官方给出的demo
const puppeteer = require('puppeteer'); (async () => { //这里和官方不同的就是,须要手动指定chromium目录所在的地址(上面连接下载以后解压),headless为true则不会打开chromium const browser = await puppeteer.launch({executablePath: '/chromium/chrome.exe',headless: false}); //至关于新建选项卡 const page = await browser.newPage(); //跳转到指定URL await page.goto('https://example.com'); //截图 await page.screenshot({path: 'example.png'}); //关闭页面或者选项卡 await browser.close(); })();
上面几行代码其实就是至关于咱们平常的一些操做:打开chrome->新建选项卡->输入url并回车->页面截图->保存,也能够看出puppeteer是站在使用者的角度去设计API。
跑通测试demo以后,来试试小程序这边,首先必须让小程序跑在chrome上面,就要用到wept了。
1. 直接在小程序根目录上面执行wept
而后打开chrome,访问http://localhost:3000/#!pages/index/index ,就能够看到小程序运行在chrome上了,接下来要让puppeteer去抓取小程序里面的内容,直接上代码
const puppeteer = require('puppeteer'); const devices = require('puppeteer/DeviceDescriptors'); (async () => { const browser = await puppeteer.launch({executablePath: '/chromium/chrome.exe',headless: true}); const page = await browser.newPage(); //设置展现的设备https://github.com/GoogleChrome/puppeteer/blob/master/DeviceDescriptors.js await page.emulate(devices['iPhone 6']); //多一个参数waitUntil,指跳转以后等待网络空闲以后再执行下一步操做,没有这个的话,截图颇有多是白屏,由于内容还没渲染出来 await page.goto('http://localhost:3000/#!pages/index/index', {waitUntil: 'networkidle'}); //小程序的内容实际上是放在一个iframe里面,外面是没法直接抓取到iframe里面的内容,因此这里须要获取页面全部的iframe const frames = await page.frames(); //根据iframe的name属性来获取正确的iframe const weChatFrame = frames.find(f => f.name() === 'view-0'); //在上下文环境中获取须要抓取的内容 const outerText = await weChatFrame.evaluate(() => { //上下文执行环境,跟H5一致 const anchors = Array.from(document.querySelectorAll('.container')); return anchors.map(anchor => anchor.textContent); }); console.log('the outerText: ', outerText); await browser.close(); })();
直接来看页面执行的效果
这样咱们就能拿到小程序的内容,便于咱们后续的单元测试,接下来咱们能够加入"抹茶"来测试输出是否符合预期,先上代码
const puppeteer = require('puppeteer'); const devices = require('puppeteer/DeviceDescriptors'); const expect = require('chai').expect; describe('output test', () => { it('should return Hello 测试账号 ', () => { (async () => { //小程序内容获取代码跟上述一致 //... expect(outerText[0]).to.equal('Hello 测试账号'); //... }) }) })
运行效果
小程序其实也有上线一个云测试,可是我以为有个很差的地方,假如你的小程序是依赖于后台CGI返回数据做为展现,那么你必须先上线CGI才能使用云测试,不够灵活,更但愿有一个能本身mock数据来测试不一样状况下的小程序的展现。
本篇文章介绍使用wept和puppeteer来对小程序作E2E测试,对于测试环境和正式环境仍是有差别的,好比Object.defineProperty
小程序是不支持这个API的,可是测试环境是能够跑通的,固然测试环境下面也能够经过某种方式(好比delete)来禁用不支持小程序的API,从而达到测试环境尽量的贴近小程序的正式环境。固然更但愿的是小程序官方能给出相应的单元测试方案吧。