扫码阅读
手机扫码阅读

《PlayWright全解析——从入门到精通》-6

794 2023-07-17

进阶应用

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' —— 失败后首次重试时录制

原文链接: https://mp.weixin.qq.com/s?__biz=MzU5ODE2OTc1OQ==&mid=2247496377&idx=1&sn=cc4ccee90f06460d5de436a6081ffa5c

TestOps 助力提升价值交付质效

27 篇文章
浏览 13.2K
加入社区微信群
与行业大咖零距离交流学习
软件研发质量管理体系建设 白皮书上线