前言
自动化测试发展到如今,各种自动化测试工具层出不穷。Selenium 无疑是其中的佼佼者,从 2016 年至今,全球流行自动化测试工具排行榜中,Selenium 一直占据着最流行工具的头把交椅。selenium 基于 webdriver 协议,以其免费、开源和强大的功能和扩展性,同时因其创立者著名咨询公司 ThoughtWorks 公司的力推,在行业得到了广泛的应用。
但在 ThoughtWorks 公司数年前发布的技术雷达(全球技术趋势的分析指南),在 E2E (端到端测试)领域中,指出了 后 Selenium 时代的一些后起之秀,其中就重点提及了Puppeteer。
We keep receiving positive feedback on “post-Selenium” web UI testing tools such as Cypress, TestCafe and Puppeteer.
…
We have good experience using “post-Selenium” web UI testing tools such as Cypress, TestCafe and Puppeteer.
…
虽然 Selenium 是 TW 公司自家产品,但是随着前端技术的发展, Selenium 也呈现出对浏览器依赖度高、对单页面类应用掌控能力不足、基于 WebDriver 协议的通信效率不高等缺点,新一代的测试工具也逐渐进入行业视野。本文我们就一起来了解一下三驾马车中的第一个: Puppeteer
Puppeteer 简介
在介绍 Puppeteer 之前,我们先了解一个背景:headless,也就是无头浏览器。很早之前,在前端测试和爬虫领域就存在无头浏览器的需求,也就是不需要浏览器的界面,纯代码环境下实现浏览器内核操作。特别是 UI 自动化测试以及希望静默完成浏览操作的场景下非常有用。当时最流行的开源 headless 是 PhantomJS,但在 google 开源的 Puppeteer 出现之后,目前 PhantomJS 已经处于终止状态,可以说 Puppeteer 是现在应用最为广泛的 headless。
那么 Puppeteer 就是 headless 吗?官方对 Puppeteer 有一个简单的定义:
Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.
可以看出,Puppeteer 实际上是一个基于CDP协议来控制 Chrome 或 Chromium 的 Node.js 的库,一般用作无头模式,但也能工作在标准模式下。
- Puppeteer 是 Node.js 库,需在 Node 环境下运行代码
- 基于 Chrome Devtools protocol
- 仅可控制 Chrome 或 Chromium
- 可配置运行模式
Puppeteer 架构
如图是 Puppeteer 的官方架构:
说明:
- Puppeteer 使用 DevTools Protocol 与浏览器 Browser 进行通信。
- Browser 浏览器实例可以包含多个浏览器上下文 BrowserContext。
- BrowserContext 用于保持浏览器 session,一个浏览器上下文可以包含多个页面。
- Page 一个 Page 最起码包含一个 frame,即 main frame,允许存在其他的 frame,这些frame 可以用 [iframe] 创建。
- Frame 一个 Frame 最起码有一个 Javascript 执行上下文环境,即默认的执行上下文环境。Frame 允许存在额外附加的上下文环境
- Worker 存在唯一的上下文环境,并可与 WebWorkers相互协作。
Puppeteer 的安装
因为 Puppeteer 实际是一个 Node 库,所以安装非常简单:
> npm install puppeteer
在安装时会同时安装 chromium,但因为众所周知的原因,国内会下载失败。所以建议使用国内源安装即可
> npm install -g cnpm --registry=https://registry.npm.taobao.org
> cnpm install puppeteer
安装后可以使用以下命令检查下安装的版本,确认安装正确
> npm ls puppeteer
Hello World
通过一个简单的例子看下 Puppeteer 的基本用法。
因为 Puppeteer 是通过 CDP 协议直接控制浏览器,所以可以实现很多浏览器层面的直接操作,比如下面这段代码,我们控制浏览器 (正常模式) 在访问我的博客网站时弹出一个对话框:
const puppeteer = require('puppeteer');
HelloWorld();
async function HelloWorld(){
const browser = await puppeteer.launch({
headless:false
});
const page = await browser.newPage();
await page.goto('https://chengxiaqiucao.github.io/');
await page.evaluate(()=>alert('hello world!'));
await browser.close();
}
具体的 js 语法如 async,await 以及箭头函数等的用法,这里不多介绍了,大家可以先查阅下 js 相关文档。
通过 node.js 执行这个 js 文件,即可运行。
node pupp_sample.js
执行效果:
Puppeteer 的主要特性
前文是一个 Puppeteer 的简单示例。我们可以看到 puppeteer 的基本用法。其实 Puppeteer 作为一个强大的 headless,有很多功能,择要总结如下:
设置浏览器启动参数
在启动浏览器的方法中,我们通过设置一些参数来配置浏览器,常用的参数有:
-
headless: true/false 设置是否启动无头模式
-
devtools: true/false 是否同时启动 devtool
-
slowMo:毫秒数。运行在 slow 模式下,每步骤操作间隔
-
timeout: 毫秒数,设置启动超时时间,默认值 30000,即 30 秒
-
executablePath: 可以使用已安装的 chrome 浏览器替换默认的 chromium 浏览器,此处设置浏览器执行文件路径
-
args:设置 chrome 浏览器支持的配置参数。
支持的详细参数参见:chrome浏览器参数。
比如args: ["--start-maximized"]
可以设置启动浏览器默认最大化。
还用上文的代码,修改一下:
const browser = await puppeteer.launch({
headless:false,
devtools:true,
slowMo:1000,
args:["--start-maximized"]
});
const page = await browser.newPage();
await page.