playwright 断言
断言在自动化测试中扮演着至关重要的角色。它们帮助我们验证应用程序的行为是否符合预期,并在发现问题时提供详细的错误信息。本文将深入探讨断言的各个层面,从基础到高级,带您逐步了解如何利用Playwright进行高效的断言。
基础篇:断言
1. 为什么需要断言
在自动化测试中,我们需要一种机制来验证应用程序的行为是否正确。断言是一种用于验证测试结果的机制,它们帮助我们确认测试是否按预期执行,并且在测试失败时提供有用的信息。
2. 断言生成器
Playwright提供了断言生成器,帮助验证元素是否存在、元素内容、元素属性等:
-
•
expect(element).toBeVisible(): 验证元素是否可见,参见上图“小眼睛”图标 -
•
expect(element).toHaveText(text): 验证元素的文本内容是否包含指定的文本,,参见上图“ab符号”图标 -
•
expect(element).toHaveAttribute(name, value?): 验证元素是否具有指定的属性,以及属性值是否符合预期,参见上图“文本”图标
3. 断言api
此外,Playwright还提供了丰富的断言api供调用,大致可以分为 基本断言、定位器断言、页面断言、接口类断言 等
基本断言
-
• 相等
expect(value).toBe(expected) //值比较
expect(value).toEqual(expected) //深度比较
-
• 不相等
expect(value).not.toBe(expected)
-
• 包含
expect(value).toContain(expected)
-
• 模式匹配
expect(value).any()
expect(value).anything()
expect(value).arrayContaining()
expect(value).closeTo()
expect(value).objectContaining()
expect(value).stringContaining()
expect(value).stringMatching()
expect(value).toMatch()
expect(value).toMatchObject()
例如
expect({
list: [1, 2, 3],
obj: { prop: 'Hello world!', another: 'some other value' },
extra: 'extra',
}).toEqual(expect.objectContaining({
list: expect.arrayContaining([2, 3]),
obj: expect.objectContaining({ prop: expect.stringContaining('Hello') }),
}));
定位器断言
-
• 可见性
expect(element).toBeVisible(); //可见
expect(element).toBeHidden(); //隐藏
expect(element).toBeInViewport(); //视图中
-
• 状态变化
expect(element).toBeChecked(); //选中
const locator = page.getByRole('textbox');
await expect(locator).toBeFocused(); //聚焦
const locator = page.locator('div.warning');
await expect(locator).toBeEmpty(); //空
const locator = page.locator('button');
await expect(locator).toBeEnabled(); //可点
-
• 元素内容
const locator = page.locator('.title');
await expect(locator).toContainText(/\d messages/); //包含
await expect(locator).toHaveText(/Welcome/);
await expect(locator).toHaveValue(/[0-9]/);
const locator = page.getByRole('textbox');
await expect(locator).toHaveId('lastname');
const locator = page.locator('#component');
await expect(locator).toHaveClass(/selected/);
页面断言
-
•
URL
await expect(page).toHaveURL(/.*checkout/);
-
•
title
await expect(page).toHaveTitle(/.*checkout/);
-
•
screenshot
await expect(page).toHaveScreenshot('image.png');
接口断言
-
•
toBeOK
await expect(response).toBeOK();
-
•
not
await expect(response).not.toBeOK();
进阶篇:软断言
1. 断言的问题
测试断言失败,后续用例都无法执行?这也是自动化测试中经常遇到的问题。 Playwright 提供了软断言Soft Assertions的支持,允许测试在遇到断言失败时继续执行,并在最后统一标记测试为失败,提升测试的灵活性。
2. 什么是软断言
软断言是一种特殊的断言方式,与传统的断言不同,软断言在遇到失败时不会立即中止测试执行,而是将测试标记为失败。这使得在测试中可以执行多个断言,即使其中一部分失败,测试仍能继续执行,方便查看所有断言的结果。
3. 在 Playwright 中使用软断言
在 Playwright 中,可以通过 expect.soft() 方法来执行软断言。
示例如下:
import { test, expect } from '@playwright/test';
test('软断言示范', async ({ page }) => {
// 在页面上执行软断言
await expect.soft(page).toHaveTitle('标题');
// 其他测试步骤
await page.goto('https://example.com');
await expect(page).toHaveTitle('Example');
});
test.afterEach(async ({ testInfo }) => {
// 在测试结束后检查是否有软断言失败
if (testInfo.errors.length > 0) {
console.error('软断言失败信息:');
for (const error of testInfo.errors) {
console.error(error.message);
console.error(error.stack);
}
}
});
4. 软断言小结
-
• 软断言适用场合,
检查多个元素状态但不希望因为一个失败而中断整个测试 -
•
expect.soft()实现软断言,testInfo.errors查看是否存在软断言失败 -
• 灵活使用软断言可以提高自动化测试的鲁棒性
高级篇:可视化回归
1. 什么是可视化回归
可视化回归测试,即Visual Regression Testing是一种自动化测试方法,用于检测页面布局和外观的变化。它通过比较页面的屏幕截图,来检测是否存在意外的视觉变化。
2. 利用snapshotAssert
Playwright提供了toMatchSnapshot()方法,用于捕获页面的屏幕截图,并将其与预期的参考截图进行比较。这种方式可以很容易地发现页面布局或样式的变化,从而确保应用程序的外观和用户体验始终如一。
3. 示例
test('可视化回归测试', async ({ page }) => {
await page.goto('https://alipan.com');
const screenshot = await page.screenshot();
expect(screenshot).toMatchSnapshot('alipan.png');
});
说明如下:
-
首次运行,生成截面截图
alipan.png -
迭代上线后,再次运行,会截图并比对,
Playwright检测视觉变化有差异,断言会失败并显示差异的详细信息,包括截图比较结果和差异的位置
结论
-
• 断言在自动化测试中扮演着至关重要的角色,它们帮助我们验证应用程序的行为是否符合预期,并在发现问题时提供详细的错误信息。通过
expect()开启断言,结合代码生成工具可以快速生成各种断言方法,如.toBeVisible()、.toContain()、.toHaveValue()等,从而有效地验证页面元素的可见性、内容、属性等。 -
• 软断言
soft()是一种特殊的断言方式,它允许测试在遇到断言失败时继续执行,并在最后统一标记测试为失败,提升了测试的灵活性。对于需要验证多个条件的测试场景,软断言能够帮助我们更好地捕获失败信息,而不至于中断整个测试流程。 -
• 利用
Playwright的toMatchSnapshot()方法可以实现可视化回归测试,自动检测页面是否发生明显的UI变化。通过对比页面截图,我们可以快速发现页面布局或样式的变化,确保应用程序的外观和用户体验始终如一。
综上所述,断言在自动化测试中是不可或缺的工具,我们可以根据项目需求灵活选用不同类型的断言,并结合软断言和可视化回归测试,提高测试的质量和效率,确保应用程序的稳定性和可靠性。
实现文件自动化下载
利用Playwright实现自动化下载文件,演示了自动化下载阿里云盘的基本步骤。详细介绍了Playwright中下载相关属性和方法,以及Promise.all()实现多文件下载。
Playwright实战自动化下载
以自动化下载阿里云盘为例:

操作步骤
-
• 首先打开页面
alipan.cn -
• 其次定位到
下载桌面端按钮,该页面有2处,任意一处都是可以的,挑选左下角那个,把鼠标移动过去,会出现版本选择,这里我们选择Windows,点击 -
• 等待文件下载完成,并断言检查
用例录制
可以用录制的方法生成测试用例:
npx playwright codegen https://alipan.cn
具体操作可以看前面的介绍文章
【playwright - CSDN App】https://blog.csdn.net/weixin_46281518/article/details/145601119?sharetype=blogdetail&shareId=145601119&sharerefer=APP&sharesource=weixin_46281518&sharefrom=link
第一篇
实现代码
import { test, expect, browser } from '@playwright/test';
const playwright = require('playwright');
test('alipan', async ({ page }) => {
await page.goto('https://www.alipan.com/');
await expect(page
.getByText('下载桌面端')
.nth(1))
.toBeVisible();
const downloadPromise = page
.waitForEvent('download');
await page
.getByText('下载桌面端')
.nth(1)
.hover();
await page
.getByRole('link', { name:'Windows' })
.nth(1)
.click();
const download = await downloadPromise;
await download
.saveAs(download.suggestedFilename());
});
几点说明
-
元素定位,采用
getByText('下载桌面端'),会命中2条数据,这里用.nth(1)选择第2条结果; -
文件下载,选择
Windows链接后,触发下载事件,需要等待文件下载完成后才能进行后续操作,.waitForEvent('download'),并保存为download -
download提供了suggestedFilename()方法获取文件名,调用saveAs()方法保存文件
Playwright中下载相关内容
download方法
在Playwright中,download对象提供了以下方法:
-
•
download.path():获取下载文件的路径。 -
•
download.saveAs(path):将下载的文件保存到指定路径。 -
•
download.failure():返回一个Promise,用于检查下载是否失败。 -
•
download.delete():删除下载的文件。
download属性
在Playwright中,download对象提供了以下属性:
-
•
download.url():返回下载文件的URL。 -
•
download.suggestedFilename():返回下载文件的建议文件名。 -
•
download.headers():返回下载文件的响应头信息。 -
•
download.finished():返回一个Promise,用于检查下载是否完成。 -
•
download.failure():返回一个Promise,用于检查下载是否失败。 -
•
download.createTime():返回下载任务创建的时间戳。 -
•
download.endTime():返回下载任务结束的时间戳。
page.on('download')
page.on('download') 是 Playwright 中用于监听文件下载事件的方法。该方法用于注册一个监听器,当页面触发文件下载事件时,该监听器会被调用。
在监听器中,我们可以获取到下载的相关信息,例如下载的文件名、文件大小等,并且可以对下载的文件进行保存或其他处理。
参考示例
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
// 监听文件下载事件
page.on('download', download => {
console.log('Download started: ', download.suggestedFilename());
// 保存下载的文件到指定路径
download.saveAs('/path/to/save/' + download.suggestedFilename());
});
// 访问包含文件下载链接的页面
await page.goto('https://example.com');
// 点击页面上的文件下载链接
await page.click('a[download]');
// 等待一段时间,确保下载完成
await page.waitForTimeout(5000);
await browser.close();
})();
说明如下:
-
•
page.on('download')方法注册了一个监听器,用于捕获页面上的文件下载事件 -
• 当页面中的文件下载链接被点击时,下载事件被触发
-
• 在监听器中将文件保存到指定的路径中,完成日志打印
Playwright实战多文件下载
Promise.all()
Promise.all() 是 JavaScript 中的一个方法,用于将多个 Promise 对象组合成一个新的 Promise 对象:
-
• 它接收一个由
Promise对象组成的可迭代对象,并返回一个新的Promise 对象。 -
• 新的
Promise对象在所有输入Promise对象都成功完成时才会被解析,否则会被拒绝,返回拒绝原因中的第一个拒绝的Promise对象的结果。示例 假设我们有一个数组urls包含多个URL地址,我们想要同时发起多个网络请求,并在所有请求都完成时获取它们的响应数据
示例:
const urls = ['https://example.com/1', 'https://example.com/2', 'https://example.com/3'];
const promises = urls.map(url => fetch(url)); // 假设 fetch 是一个异步函数,返回一个 Promise
Promise.all(promises)
.then(responses => Promise.all(responses.map(response => response.json())))
.then(dataArray => {
// 所有请求成功完成后的数据数组
console.log(dataArray);
})
.catch(error => {
// 处理任何一个请求失败的情况
console.error('At least one request failed:', error);
});
说明如下:
-
•
Promise.all()同时发起多个网络请求,并在所有请求完成后,再次使用 Promise.all() 将所有响应转换为 JSON 数据 -
• 通过
.then()处理所有请求成功完成后的数据,以及通过.catch()处理任何一个请求失败的情况
总之,Promise.all() 是一个非常有用的工具,用于管理多个异步操作,使得它们能够并行执行,并且在所有操作完成后统一处理结果。
多文件下载
当需要下载多个文件时,可以利用 Promise.all() 来同时发起多个文件下载请求,并在所有下载完成后进行处理。
示例如下:
const playwright = require('playwright');
const fs = require('fs');
async function downloadFiles(urls) {
const browser = await playwright.chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
const downloadPromises = urls.map(async (url, index) => {
// 在新标签页中打开文件下载链接
await page.goto(url);
// 等待文件下载完成的事件
const [download] = await Promise.all([
page.waitForEvent('download'), // 等待文件下载完成
page.click('a') // 触发文件下载链接点击事件
]);
// 获取文件名
const fileName = download.suggestedFilename();
// 将文件保存到本地
await download.saveAs(`file_${index + 1}_${fileName}`);
console.log(`File ${fileName} downloaded successfully.`);
});
try {
await Promise.all(downloadPromises);
console.log('All files downloaded successfully.');
} catch (error) {
console.error('Failed to download one or more files:', error);
}
await browser.close();
}
// 示例:下载多个文件
const urls = [
'https://example.com/file1.pdf',
'https://example.com/file2.docx',
'https://example.com/file3.xlsx'
];
downloadFiles(urls);
说明如下:
-
定义了一个名为
downloadFiles的异步函数,该函数接收一个URL数组作为参数,然后使用Promise.all()方法来同时发起多个文件下载请求 -
每个
URL,在新的浏览器上下文中打开一个页面,并在页面中点击文件下载链接。 -
等待文件下载完成的事件,并使用
download.saveAs()方法将下载的文件保存到本地。 -
通过
Promise.all()来等待所有文件下载完成,或捕获其中任何一个下载失败的情况
小结
-
Playwright中利用定位和点击等触发下载操作,可以利用codegen录制代码,再手动调整修改 -
Playwright中下载触发download事件,.waitForEvent('download') -
用
download.saveAs()保存下载文件 -
多文件下载,用
Promise.all()处理
更多推荐
所有评论(0)