介绍
Puppeteer
puppeteer出自谷歌,是一套Node.js库提供API来控制Chromium浏览器,puppeteer意为控制木偶的人,也就是可以在Node.js里像控制木偶一样控制Chromium浏览器,默认是headless无头环境,所以可以在服务端直接运行,不需要任何界面,支持跨平台
Playwright
playwright出自微软,也提供了API来控制浏览器,还支持做自动化测试,也是headless无头环境,支持服务端无界面运行,跨平台,但除了支持Chromium,还额外多支持了Firefox/WebKit核浏览器
- playwright: Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API
- Playwright (https://playwright.dev/)
Headless
两个库都是支持Headless,那为什么需要headless?
其实headless最终就是为了实现浏览器能更好的自动化运行,自动化运行一般都是在服务端自己跑就好,那也不需要给用户看界面,且服务端都是Linux的,也没有显示器,所以浏览器直接砍掉界面显示就是Headless,但此时也不影响界面的渲染
但一开始没有浏览器是支持headless的,这时候诞生了一个叫PhantomJS的库支持了headless,让我们做前端自动化测试的看到了一种黑科技的出现
有了headless的支持,像前端单元测试,Web UI自动化测试都能很好的实现,但此时的Headless也有一些问题:
- 比如PhantomJS的运行环境和真实的浏览器还存在一些差异
- 单元测试在PhantomJS下能过,但在浏览器里未必就通过
- PhantomJS的速度和性能不能媲美真实浏览器,比如Chromium,一旦运行过多的case,也会不稳定,随机失败等
- PhantomJS存在一些浏览器的API不支持不兼容的情况,比如setTimeout还有一些css3的animation的不支持等
大概在2017年,谷歌突然宣布说Chromium原生就支持Headless(估计是看到了PhantomJS的火爆),意味着直接可以用真实的浏览器进行测试了,也意味着PhantomJS的下岗(2018年PhantomJS最终版本停留在了2.1.1),那么接下来就是Puppeteer的时代
Puppeteer的问题
Puppeteer非常好用,完美解决了浏览器的Headless运行,且性能和稳定性都非常优秀,因为本身就是原生的浏览器,但也存在一些小问题,而Playwright不但包含了Puppeteer几乎所有功能,同时还较好的解决了这些问题
Chromium下载的问题
Puppeteer本身支持一个Node.js的库,并不包括Chromium浏览器,所以需要提前下载Chromium浏览器(在npm install的时候),会自动根据平台是windows,linux,Mac自动下载对应的包到本机,并解压安装在本地
所以Puppeteer提供了 puppeteer和puppeteer-core两个包,puppeteer-core不会自动下载浏览器,而默认puppeteer包支持自动下载Chromium浏览器,问题就出在这里
如图所示,Puppeteer会将Chromium下载到它自己的node_modules/puppeteer/.local-chromium下面,且有400多兆的大小,如果有多个项目呢;而且经常更新node_modules造成下载浪费;还有就是默认下载是从google的镜像,有时候还特别慢偶尔无法连接,导致安装失败,这时候需要借助一个库解决
可以将Chromium安装到用户目录(非项目node_modules目录),并缓存起来,且所有项目共用,还能自动从自定义镜像下载包,避免连接失败或者访问慢的问题
而Playwright也提供了playwright和playwright-core两个包,但playwright本身就选择将浏览器安装在用户目录(如下图node_modules/playwright下仅有少数文件),也就是直接解决了上面的问题
经过搜索发现playwright将多个浏览器都下载到了以下目录(windows环境)实现了用户级的共享
C:\Users\[user]\AppData\Local\ms-playwright
下载的服务器,从当前看也有3个CDN
const PLAYWRIGHT_CDN_MIRRORS = ['https://playwright.azureedge.net', 'https://playwright-akamai.azureedge.net', 'https://playwright-verizon.azureedge.net'];
而Puppeteer仅有一个
host: 'https://storage.googleapis.com'
不过通过puppeteer-chromium-resolver可以自定义host来支持其他镜像下载,比如淘宝镜像
const PCR = require("puppeteer-chromium-resolver");
const option = {
revision: "",
detectionPath: "",
folderName: ".chromium-browser-snapshots",
defaultHosts: ["https://storage.googleapis.com", "https://npm.taobao.org/mirrors"],
hosts: [],
cacheRevisions: 2,
retry: 3,
silent: false
};
const stats = await PCR(option);
const browser = await stats.puppeteer.launch({
headless: false,
args: ["--no-sandbox"],
executablePath: stats.executablePath
}).catch(function(error) {
console.log(error);
});
const page = await browser.newPage();
await page.goto("https://www.npmjs.com/package/puppeteer-chromium-resolver");
await browser.close();
此时chromium会被下载到用户的目录,并同样实现用户级共享
C:\Users\[user]\.chromium-browser-snapshots
多浏览器支持的问题
显然Puppeteer比Playwright少支持了Firefox/WebKit核浏览器,这个其实是问题,但也不是什么大问题。
因为最开始的时候,我们其实更多的需求是想要支持IE浏览器,当年问题多的也是IE浏览器,而今天IE也正式退役了,被Edge替换(Edge本身也是chromium核)
同时Firefox也很少人用了,且本身和Chromium差异化不大,也就是chromium测试通过Firefox大概率通过,也没有多少必要去进行单独的全面测试,WebKit也类似,所以仅支持chromium反而还更轻便。
而从测试总的投入产出比来看,支持多个浏览器投入产出比较低,所有的case多跑一遍就花费了一倍的时间,也消耗服务器资源,如果因为一些不稳定造成的问题,还要消耗人力去解决,而产出仅仅是为了很少人使用的Firefox上一个很小的问题,所以也需要管理者去衡量,至少统计一下自己的产品有多少用户是Firefox
是否支持自动化测试
从设计上讲,本身也不是什么问题,因为单一职责,Puppeteer只需要把对浏览器的控制做好就行了,至于测试,可以交给比如Mocha.js这些工具去做,丰富的断言库,更具定制化,但需要使用者自行开发并整合。
而Playwright自带一个测试库@playwright/test
const { test, expect } = require('@playwright/test');
test('basic test', async ({ page }) => {
await page.goto('https://playwright.dev/');
const name = await page.innerText('.navbar__title');
expect(name).toBe('Playwright');
});
同时直接支持了同jest一样的断言expect,使用者可以直接使用,非常的方便 如果要基于playwright封装一个UI自动化测试框架也不难(源码 cenfun/monocart: Web UI automation test tool based on playwright (github.com))
结论
Playwright几乎就完全覆盖了Puppeteer所有功能,且做了更多更好的支持,所以Puppeteer的替代者就是Playwright没问题。
本人是Puppeteer重度使用者,为什么会知道并转向Playwright?
其实不难发现Puppeteer的最大贡献者是@aslushnikov,但同时也是Playwright前3的贡献者,且@aslushnikov在自己介绍里写了@microsoft,两个库都是同样的贡献者在维护,难怪API几乎都兼容,两个库相互迁移都非常容易。
其次就是Puppeteer基于趋于稳定,如果有breaking change一般都是chromium本身的,而Playwright还在朝着相关生态继续发展,playwright并不仅支持Node.js,还支持了python,java、.net
两个都是非常优秀的库,看用户怎么根据自身情况选择即可。