在前面不少文章中,咱们都介绍了单元测试。若是你了解单元测试,或者读过我以前写的单元测试的文章,那么你必定知道,单元测试的测试对象是单独的、隔离的小代码片断或者代码单元。与单元测试不一样,端对端测试的测试对象则是页面上的用户交互,咱们对底层实现一无所知,也就是说咱们的测试是黑盒的。另外,一些跨页测试,好比连接检查,登录跳转等功能必须使用端对端测试才能检查出来,单元测试是没法测这些功能的。之前我只写单元测试,不写端对端测试,结果有一次所负责的页面上有个连接不能点了,还好及时修复,但仍是让我感觉到了端对端测试,或者说是自动化端对端测试的重要性。git
Puppeteer 默认状况下,全部操做是不可见的,若是你想像我这样监视发生的一切,须要将 Puppeteer 的
headless
选项设为false。
github
我使用过不少端对端测试的轮子,好比 Selenium、Appium、Protractor、Zombie.js、Cypress、Nightmare、Puppeteer 等。但最终仍是选择了 Puppeteer,由于 Selenium 和 Appium 太难用了,Protractor 则像是专门给 Angular 设计的,Zombie.js 太简单了,并且使用的浏览器内核不是市面上流行的任何一个,而是自定义的。Cypress 有平台依赖,我只是想要个本地运行的工具而已。只剩 Nightmare 和 Puppeteer 了,其实这两个都是好选择,可是我是个 star 控,Puppeteer 的 star 比 Nightmare 多,因此我选择了 Puppeteer。但事实上 Nightmare 更流行,由于我发现蚂蚁最新的那个 Antd Pro 就是用的 Nightmare,阿里一些其余端对端测试的工具也有基于 Nightmare 来作的。因此若是你想使用 Nightmare 来进行自动化端对端测试也是彻底没有问题的。npm
使用 Puppeteer 很是简单,首先安装它:json
yarn add puppeteer # or "npm i puppeteer"
const puppeteer = require('puppeteer');而后就能够在 Node 脚本中使用它了!来个简单的导航并截屏例子吧!这个例子先启动浏览器,导航到 https://baidu.com
页面,而后截屏并保存为 baidu.png
,最后关闭浏览器。浏览器
(async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://baidu.com'); await page.screenshot({path: 'baidu.png'}); await browser.close(); })();
将上述代码写进 Node 脚本中,并运行就能够了!看下生成的截图:babel
是否是很简单?短短几行代码就作了这么多事。若是你对 async
、await
这种语法不熟悉,那么我强烈建议你去学习一下,这种语法在 Puppeteer 中使用率简直不要过高。不过也不要担忧学习成本, async
、await
语法很是简单,就是 Promise 的一种新写法而已,让你的异步代码看起来就像是同步的同样。less
要知道,Puppeteer 是一个浏览器自动化工具,它只能进行浏览器的自动化,自己并不具备测试功能。我说的测试功能指的是,断言啊,生成测试报告啊这些功能。若是你不熟悉这些概念,那么请移步:《Jest 单元测试入门》。因此,除了 Puppeteer 外,咱们还须要使用一个测试工具,我选择了 Jest,理由在以前的博文中已经说过不少遍了,这里再也不赘述。使用 Jest 很是简单,只须要异步
具体用法看以前的博文:《Jest 单元测试入门》。async
讲完了 Puppeteer 和 Jest 的基本用法,咱们来看一下,如何将二者结合起来使用。其实将 Jest 与 Puppeteer 结合使用很是简单,由于 Puppeteer 的本质就是个 NPM 模块而已,因此咱们只须要在 Jest 测试脚本中引入它便可使用了。为什么如此呢?由于测试脚本的本质其实也是 Node 脚本,既然是 Node 脚本那么固然能够直接引入 NPM 模块来用了!函数
须要注意的是,由于 Puppeteer 一般须要使用
async
、await
这种语法,若是你的 Node 版本在7.6及以上,那么恭喜你,直接大胆使用,不然须要在 Jest 中配置 Babel,来使其支持这种新语法。在 Jest 中配置 Babel 很是简单,你能够在这里找到具体方法。
让咱们来个小例子吧!首先,咱们打开百度页面,并断言百度页面的 title
是 百度一下,你就知道
。那么测试脚本应该这么写:
const puppeteer = require('puppeteer'); test('baidu title is correct', async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://baidu.com'); const title = await page.title(); expect(title).toBe('百度一下,你就知道'); await browser.close(); });
$ npm test看到 test
和 expect
两个全局函数了吗?这就是 Jest 所赋予的能力,让你能够编写测试用例和断言。最后在命令行输入 npm test
,即 jest
(这是在 package.json 中配置好的命令),便可看到生成的测试报告:
> fe-test@1.0.0 test /Users/liuyiqi/code/fe-test > jest PASS puppeteer-demo/baidu-title.test.js PASS puppeteer-demo/screenshot.test.js Test Suites: 2 passed, 2 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 3.241s Ran all test suites.
https://github.com/lewis617/fe-test/tree/master/puppeteer-demo其中 screenshot.test.js
是截屏的那个例子,baidu-title.test.js
是断言百度首页 title 的例子。你能够在这里找到源码:
至此,使用 Jest 与 Puppeteer 来进行端对端测试的基本用法就讲完了。下篇博文咱们将会集中讲解经常使用 Puppeteer 功能,好比模拟用户输入、执行 JavaScript 脚本、获取某个 DOM 节点中的文本等。