本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2022年11月28日 统计字数: 5849字 阅读时间: 12分钟阅读 本文链接: https://soulteary.com/2022/11/28/playwrights-concise-introductory-tutorial-recording-automated-test-cases-and-using-it-with-docker.html ----- # Playwright 简明入门教程:录制自动化测试用例,结合 Docker 使用 本篇文章聊聊如何使用 Playwright 进行测试用例的录制生成,以及如何在Docker 容器运行测试用例,或许是网上最简单的入门教程。 ## 写在前面 [Playwright](https://playwright.dev/) 是微软出品的 Web 自动化测试工具和框架,和 [Google Puppeteer](https://pptr.dev/) 有着千丝万缕的关系。前一阵答应了小伙伴,要做一些自动化测试相关的分享。本篇作为第一篇,聊聊怎么简单的玩 Playwright 。 在 [playwright](https://github.com/microsoft/playwright) 或者 [puppeteer](https://github.com/puppeteer/puppeteer) 的开源项目中,不论是文档还是示例,有不少内容倾向于编写代码的方式(`Coding`)来进行自动化测试相关的动作。 然而,需要和页面打交道的前端交互测试,有一个麻烦的事儿,就是我们需要不停在浏览器和代码编辑器中进行切换,定位要交互的元素,把要操作的元素的路径、位置拿到,思考要怎么模拟用户的操作,触发页面的事件或者程序中内置钩子方法,然后切换到代码编辑器里,再编写胶水逻辑,往复循环数次,完成基础的测试程序。接下来,还要和写被测试代码一样,验证程序运行是否正确等等,**整个操作流程其实还是挺麻烦的**。 但这就完事了嘛?并没有,面向用户的界面的迭代变化频率是非常高的,基于界面元素构建的测试程序自然也要跟着变,那么我们面临的就是不停的折腾自己,**有没有省事儿一点的方法呢**? 好在我们还有另外一种选择,通过“录制为主,编写为辅”的方式来完成测试程序,而不是用上面的方式循环的折腾自己,**毕竟偷懒是工程师的美德嘛**。 ## 搞定 Playwright 本地录制环境 我们可以使用 `Playwright Python` 来完成简单的测试用例录制,关于 Python 的安装, 就不多赘述了,在 macOS 和 Ubuntu 等操作系统中是内置的 Runtime(也可以使用 `brew` 或者 `apt` 来安装或者进行升级),在 Windows 中,我们可以通过非常多的方式来完成安装。 如果你希望更快的完成 Playwright 的 Python PyPI 软件包的下载安装,可以执行下面的命令,替换软件源为清华源: ```bash pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple ``` ### 下载基础软件工具 接着,我们执行 `pip3 install playwright` 就能够完成 playwright Python 版基础程序的安装了啦: ```bash ... Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting playwright Downloading https://pypi.tuna.tsinghua.edu.cn/packages/97/35/28f880594a6e0b89475e21073b83ab374e522ab1fbf86849585ecc4a4e19/playwright-1.28.0-py3-none-macosx_11_0_universal2.whl (30.6 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 30.6/30.6 MB 255.8 kB/s eta 0:00:00 ... ... Installing collected packages: typing-extensions, greenlet, pyee, playwright ... ... Successfully installed greenlet-2.0.1 playwright-1.28.0 pyee-9.0.4 typing-extensions-4.4.0 ``` 完成基础软件的安装之后,我们执行 `playwright` 能够看到程序 CLI 的基本用法。 ```bash Usage: playwright [options] [command] Options: -V, --version output the version number -h, --help display help for command Commands: open [options] [url] open page in browser specified via -b, --browser codegen [options] [url] open page and generate code for user actions install [options] [browser...] ensure browsers necessary for this version of Playwright are installed install-deps [options] [browser...] install dependencies necessary to run browsers (will ask for sudo permissions) cr [options] [url] open page in Chromium ff [options] [url] open page in Firefox wk [options] [url] open page in WebKit screenshot [options] capture a page screenshot pdf [options] save page as pdf show-trace [options] [trace...] show trace viewer help [command] display help for command ``` 到现在为止,我们距离完成本地环境的安装还差一步,因为现在我们只有软件基础框架,并没有要进行测试的浏览器环境(Chrome、Firefox 等等),所以我们还要进行浏览器环境下载。 ### 下载需要的浏览器环境 浏览器环境的下载需要使用 `playwright install` 命令,目前支持通过命令下载下面的浏览器:chromium、chrome、chrome-beta、msedge、msedge-beta、msedge-dev、firefox、webkit。 当然,不同版本的 playwright 可能支持的浏览器列表是不同的,我们可以通过 `playwright install --help` 来查看下载的 playwright 到底支持什么浏览器。 ```bash playwright install --help Usage: playwright install [options] [browser...] ensure browsers necessary for this version of Playwright are installed Options: --with-deps install system dependencies for browsers --dry-run do not execute installation, only print information --force force reinstall of stable browser channels -h, --help display help for command Examples: - $ install Install default browsers. - $ install chrome firefox Install custom browsers, supports chromium, chrome, chrome-beta, msedge, msedge-beta, msedge-dev, firefox, webkit. ``` 比如,我们只需要测试 Chrome 环境下的程序表现,那么可以执行下面的命令: ```bash playwright install chrome ``` ## 完成第一个测试用例 当我们完成 Playwright 的环境安装和配置之后,我们就可以进行第一个测试用例的录制了。 “搜索”需求是一个有趣的例子,可以覆盖用户在页面中常见的交互动作,包含:打开页面、选择可交互的页面替换元素(Input)、跳转新页面等等。 前一阵“宝可梦”发布了新版本,作为一个还没开始玩的用户,难免对这款游戏心心念念。那么测试用例,就选择通过录制用户在搜索引擎中搜索“宝可梦”新游戏百科词条,在新窗口中打开词条中游戏的第一条宣传视频,来解解馋吧。 ### 自动化录制完成测试用例初版 接下来,我们先来创建一个目录,用于保存接下来生成的测试程序文件: ```bash mkdir -p playwright cd playwright ``` 接着,执行下面的命令,程序将自动打开两个窗口,包含一个浏览器窗口(起始页面是 `https://cn.bing.com`,当我们完成录制,结果将保存在 `pokemon.js` 文件中): ```bash playwright codegen -o pokemon.js --target javascript https://cn.bing.com ``` ![Playwright 自动打开交互窗口](https://attachment.soulteary.com/2022/11/28/step1.png) 我们在搜索框中输入“宝可梦朱紫”,然后和平时一样敲击回车键(也可以戳搜索按钮),页面会来到搜索结果页。同时,Playwright Inspector 窗口中,会生成模拟我们交互行为的代码。 ![Playwright 录制的搜索过程](https://attachment.soulteary.com/2022/11/28/step2.png) 我们点击第一条搜索结果:“百科内容”,将打开一个新的窗口。 ![Playwright 录制新窗口内容](https://attachment.soulteary.com/2022/11/28/step3.png) 接着,我们选择页面中的第一个视频元素,将出现一个视频播放器。如果浏览器的解码器正常的话,我们将能够顺利得到播放的视频画面。这里因为默认启动的浏览器环境中,缺少一些解码器,所以无法进行播放。后续的文章中我将介绍如何解决这个问题,因为不是本篇文章的重点,所以就不展开啦。 ![Playwright 打开的播放器窗口](https://attachment.soulteary.com/2022/11/28/step4.png) 目前为止,我们已经完成了本小节设置的测试目标,所以可以关闭窗口,完成录制。当我们关闭测试使用的浏览器窗口之后,录制代码将自动保存在我们的文件夹中。 使用 `cat pokemon.js` 命令查看代码,可以看到类似下面的内容: ```js const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch({ headless: false }); const context = await browser.newContext(); const page = await context.newPage(); await page.goto('https://cn.bing.com/'); await page.getByRole('searchbox', { name: '输入搜索词' }).click(); await page.getByRole('searchbox', { name: '输入搜索词' }).fill('宝可梦朱紫'); await page.getByRole('searchbox', { name: '输入搜索词' }).press('Enter'); const [page1] = await Promise.all([ page.waitForEvent('popup'), page.getByRole('link', { name: '宝可梦朱·紫_百度百科' }).click() ]); await page1.locator('#J-video-list div').filter({ hasText: '一分钟了解游戏宝可梦朱·紫 00:55' }).nth(2).click(); await page1.locator('svg').filter({ hasText: '.st0{fill:none;}' }).click(); await page1.close(); await page.close(); // --------------------- await context.close(); await browser.close(); })(); ``` ### 使用 Node.js 来验证测试用例是否可用 通过 Playwright 生成的代码很多时候并不是完全“work”的,我们可以在完成录制之后,通过 Node.js 来进行测试用例的验证。(你也可以切换为程序支持的、你喜欢的其他语言) 通过 Node 执行我们生成的代码文件: ```js node pokemon.js ``` 运行我们在文字上面小节中生成的代码,将会自动打开一个新的浏览器窗口,然后在百科页面不停的上下滚动,好像在寻找着什么东西。不久之后,我们将得到一个执行超时报错: ```js node:internal/process/promises:246 triggerUncaughtException(err, true /* fromPromise */); ^ locator.click: Timeout 30000ms exceeded. =========================== logs =========================== waiting for locator('#J-video-list div').filter({ hasText: '一分钟了解游戏宝可梦朱·紫 00:55' }).nth(2) locator resolved to visible
attempting click action waiting for element to be visible, enabled and stable element is visible, enabled and stable scrolling into view if needed done scrolling