使用 Jest 与 Puppeteer 来进行界面自动化测试

UI自动化测试 vs. 单元测试

在前面不少文章中,咱们都介绍了单元测试。若是你了解单元测试,或者读过我以前写的单元测试的文章,那么你必定知道,单元测试的测试对象是单独的、隔离的小代码片断或者代码单元。与单元测试不一样,端对端测试的测试对象则是页面上的用户交互,咱们对底层实现一无所知,也就是说咱们的测试是黑盒的。另外,一些跨页测试,好比连接检查,登录跳转等功能必须使用端对端测试才能检查出来,单元测试是没法测这些功能的。之前我只写单元测试,不写端对端测试,结果有一次所负责的页面上有个连接不能点了,还好及时修复,但仍是让我感觉到了端对端测试,或者说是自动化端对端测试的重要性。git

Puppeteer 默认状况下,全部操做是不可见的,若是你想像我这样监视发生的一切,须要将 Puppeteer 的 headless 选项设为 false。github

使用 Puppeteer 进行浏览器自动化

我使用过不少端对端测试的轮子,好比 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();
})();

  

image将上述代码写进 Node 脚本中,并运行就能够了!看下生成的截图:babel

是否是很简单?短短几行代码就作了这么多事。若是你对 asyncawait 这种语法不熟悉,那么我强烈建议你去学习一下,这种语法在 Puppeteer 中使用率简直不要过高。不过也不要担忧学习成本, asyncawait 语法很是简单,就是 Promise 的一种新写法而已,让你的异步代码看起来就像是同步的同样。less

使用 Jest 来进行测试

要知道,Puppeteer 是一个浏览器自动化工具,它只能进行浏览器的自动化,自己并不具备测试功能。我说的测试功能指的是,断言啊,生成测试报告啊这些功能。若是你不熟悉这些概念,那么请移步:《Jest 单元测试入门》。因此,除了 Puppeteer 外,咱们还须要使用一个测试工具,我选择了 Jest,理由在以前的博文中已经说过不少遍了,这里再也不赘述。使用 Jest 很是简单,只须要异步

  • 安装 Jest
  • 编写测试脚本 *.test.js
  • 最后在终端中输入 jest 命令运行测试

具体用法看以前的博文:《Jest 单元测试入门》。async

将 Jest 与 Puppeteer 结合使用

讲完了 Puppeteer 和 Jest 的基本用法,咱们来看一下,如何将二者结合起来使用。其实将 Jest 与 Puppeteer 结合使用很是简单,由于 Puppeteer 的本质就是个 NPM 模块而已,因此咱们只须要在 Jest 测试脚本中引入它便可使用了。为什么如此呢?由于测试脚本的本质其实也是 Node 脚本,既然是 Node 脚本那么固然能够直接引入 NPM 模块来用了!函数

须要注意的是,由于 Puppeteer 一般须要使用 asyncawait 这种语法,若是你的 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 节点中的文本等。

相关文章
相关标签/搜索