《PlayWright全解析——从入门到精通》-6
进阶应用
HTTP请求的拦截
可能存在这样的几种情况,一种,是后端的API接口可能还没有完全做好,或者暂时有问题,或者是第三方的,没有测试环境给我们,所以不能直接去调用,那么这时候就需要对这类接口进行Mock。
看例子:
1 2 3 4 5 6 |
await page.route('https://dog.ceo/api/breeds/list/all', async route => { const json = { message: { 'test_breed': [] } }; await route.fulfill({ json }); }); |
当然,不仅仅可以mock,还可以对实际接口访问后的结果进行修改:
1 2 3 4 5 6 |
await page.route('https://dog.ceo/api/breeds/list/all', async route => { const response = await route.fetch(); // 先去做请求 const json = await response.json(); // 将响应的body部分取出来 json.message['big_red_dog'] = []; // 修改响应的'big_red_dog'的值 await route.fulfill({ response, json }); // 返回 }); |
不仅仅是接口,还可以对请求的资源做处理,比如我们可以阻止页面上所有css资源文件的下载:
1 2 3 4 5 6 7 8 9 10 11 12 |
// example.spec.ts测试案例文件 import { test, expect } from '@playwright/test'; test.beforeEach(async ({ context }) => { // 所有结尾是css的请求,都abort await context.route(/.css$/, route => route.abort()); }); test('loads page without css', async ({ page }) => { await page.goto('https://playwright.dev'); // ... }); |
对于需要进行代理设置的,也可以采用设置proxy的方式处理:
1 2 3 4 5 6 7 8 9 10 11 |
// 在配置文件中定义全局代理 import { defineConfig } from '@playwright/test'; export default defineConfig({ use: { proxy: { server: 'http://myproxy.com:3128', username: 'usr', password: 'pwd' } } }); |
还可以对网络请求进行监控,比如下面的例子,我们定义了对请求和响应的监控:
1 2 3 4 |
page.on('request', request => console.log('>>', request.method(), request.url())); page.on('response', response => console.log(', response.status(), response.url())); await page.goto('https://example.com'); |
还可以定义一个请求事件,主动等待请求完成后再操作:
1 2 3 4 |
// 匹配/api/fetch_data这个接口的请求 const responsePromise = page.waitForResponse('**/api/fetch_data'); await page.getByText('Update').click(); const response = await responsePromise; |
截屏
可以将当前页面截屏保存到文件:
1
|
await page.screenshot({ path: 'screenshot.png' });
|
如果当前页面很长,存在滚动条,可以使用fullPage来完整截图:
1
|
await page.screenshot({ path: 'screenshot.png', fullPage: true });
|
还可以将截图以base64的编码方式保存到buffer中:
1 2 |
const buffer = await page.screenshot(); console.log(buffer.toString('base64')); |
对单个元素进行截图也是可以的:
1
|
await page.locator('.header').screenshot({ path: 'screenshot.png' });
|
视觉对比
在PlayWright中,可以使用await expect(page).toHaveScreenshot()
来对当前页面截图进行对比:
1 2 3 4 5 6 7 |
// example.spec.ts import { test, expect } from '@playwright/test'; test('example test', async ({ page }) => { await page.goto('https://playwright.dev'); await expect(page).toHaveScreenshot(); }); |
当首次运行时,会报一个错:
Error: A snapshot doesn't exist at example.spec.ts-snapshots/example-test-1-chromium-darwin.png, writing actual.
,原因是在首次运行的时候还没有生成截图,所以无法进行截图对比,但是会在创建一个example.spec.ts-snapshots
目录,并在其中生成截图。截图的名字类似这样:example-test-1-chromium-darwin.png
,名字中的chromium-darwin
代表了浏览器和操作系统。如果更换到别的系统或者浏览器,也会出现找不到截图的问题,可以使用命令行进行截图的更新:
1
|
npx playwright test --update-snapshots
|
截图名称也是可以更改的:
1
|
await expect(page).toHaveScreenshot('landing.png');
|
第二次运行测试时,就会进行截图的对比。
对比截图,可以设置各种参数,比如可以设置最大允许多少个像素点的差异,来实现一定范围内的模糊对比,这是比较好的功能:
1 2 3 4 5 6 |
import { defineConfig } from '@playwright/test'; export default defineConfig({ expect: { toHaveScreenshot: { maxDiffPixels: 100 }, }, }); |
这是全局设置,也可以在测试案例中单独设置:
1 2 3 4 5 6 7 8 9 10 11 12 |
// example.spec.ts import { test, expect } from '@playwright/test'; test('example test', async ({ page }) => { await page.goto('https://playwright.dev'); await expect(page).toHaveScreenshot( 'landing.png', { maxDiffPixels: 100 }, ); }); |
看下还能支持哪些参数属性呢?toHaveScreenshot
方法的参数如下:
-
name:
String
或者Array
类型,表示截图的名称。 -
options: 可选参数,对象类型,包含以下属性:
-
animations,可选参数,值为”disabled”或”allow”,默认值为”disabled”。当设置为”disabled”时,CSS的动画属性、渐变属性,以及Web自身的动画元素,都会被停止。当动画属于有限动画时,将会触发
transitionend
事件,让动画快进到最后结束。如果是无限循环动画效果,则会取消无限循环属性,并快进停止到结束。这样对页面存在一些动态元素时,进行截图对比是很有利的。 -
caret,可选参数,值为”hide”或”initial”,默认为”hide”,这个参数表示是否要隐藏输入框中的光标,就是那个竖线闪烁的东西,这个也会影响图像对比,所以隐藏是必须的。
-
mask,可选参数,类型为
Array
,这里将可以指定定位的元素位置用一个粉色的框#FF00FF
遮盖,这样可以忽略掉一些不需要对比的元素。 -
maxDiffPixelRatio,数字型可选参数,值从0到1,表示最大多少比例的像素可以允许不同。
-
maxDiffPixels,数字型可选参数,表示最多允许多少像素不同。
-
omitBackground,布尔型可选参数,表示是忽省略背景。默认为
false
。 -
scale,可选参数,值为”css”或者”device”,默认为”css”,这个参数表示缩放是和css相关还是和设备相关,css相关就是正常像素大小,而和设备相关,那就会因为设备DPI的不同而不同。
-
threshold,可选数字型参数,值在0到1之间,默认值为0.2,这个参数代表两张图同一个像素的颜色的差别接受程度,0表示完全一致,1表示可有所偏差,这个值的含义可以参考YIQ。
-
timeout,数字型可选参数,单位是毫秒,用于指定对比的超时时间。
-
录制视频
PlayWright可以在测试的过程中进行录屏操作,录制完成的视频保存在测试结果目录下,默认为test-results
目录,录屏在配置文件中进行配置。实际上,录屏使用的是ffmpeg这个工具。
还记得我们在初始化PlayWright的时候会自动下载浏览器吗?实际上在下载浏览器的同时,还会根据你的系统,下载对应的ffmpeg
工具。
先看一个例子,这个例子定义了当测试失败后的首次重试时,会进行视频录制:
1 2 3 4 5 6 |
import { defineConfig } from '@playwright/test'; export default defineConfig({ use: { video: 'on-first-retry', }, }); |
video属性的值可以是一个对象,也可以是一个字符串,这个字符串必须是”off”|”on”|”retain-on-failure”|”on-first-retry”这几个值中的之一。
如果是对象,有这么几个属性:
-
mode,串必须是”off”|”on”|”retain-on-failure”|”on-first-retry”这几个值中的之一
-
size,可选参数,是个对象,有两个属性:
-
width,数字类型,录像的视频宽度
-
height,数字类型,录像的视频高度
-
如果这个size参数不设置,那么视频的大小会和viewPort参数设置的一致。
解释一下mode
的4个值的含义:
-
'off'
—— 不进行录制 -
'on'
—— 每个测试都会录制 -
'retain-on-failure'
—— 每个测试都会录制,但是会在最后删除所有成功的测试的录像,只保留失败的测试的录像 -
'on-first-retry'
—— 失败后首次重试时录制