![图片[1]-Playwright实战 – 从录制生成代码到有效组织测试用例-365博客](https://qiniu.dianchuang365.cn/2025/02/20250202122925523.png)
简介:Playwright的录制功能提供了快速生成代码的方式,然而在实际项目中,这些自动化测试的代码因不稳定性而难以维护。本教程旨在帮助你掌握如何通过使用Playwright的API重新组织和优化自动生成的代码,从而提高测试用例的稳定性和可维护性。
概述
Playwright 的录制功能确实为自动化测试提供了一个快速入门的途径,能够帮助我们快速生成代码,实现从 0 到 1 的自动化测试。这是它的优点——快速、低成本,特别适合初学者或者需要快速验证想法的场景。
- 稳定性差:这次测试能通过,下次可能就失败了,尤其是页面结构稍有变化时。
- 可维护性低:代码通常比较冗长,而且有很多重复的部分。比如每个测试用例都会包含登录操作,随着项目迭代,这种重复代码会越来越多。
- 可复用性差:录制的代码往往缺乏模块化设计,后续修改和维护的成本会越来越高。
为了解决这些问题,我们可以借助 Playwright 提供的 API 对录制的代码进行重构,重新组织和管理测试用例。这样不仅能提高代码的稳定性和可维护性,还能增强代码的可复用性,让自动化测试更加高效。
这篇教程将结合 Playwright 的特性,帮助你掌握以下内容:
- 如何从零开始编写测试用例
- 如何组织和管理测试用例
- 常用的 API 使用技巧
- 元素定位策略
- 如何编写有效的断言
第一个test case
用playwright
写自动化测试非常简单
只关注2件事
- 执行的操作
- 断言的内容
其他复杂细节比如等待
、重试
,框架本身已经帮我们处理好了
例如在playwright
在example
中提供的例子
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page
.goto('https://playwright.dev/');
// 标题包含Playwright
await expect(page)
.toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
// 操作
await page
.getByRole('link', { name: 'Get started' })
.click();
// 断言
await expect(page.getByRole('heading', { name: 'Installation' }))
.toBeVisible();
})
解释如下:
• page.goto()
操作访问指定网页
• page.getByRole().click()
操作定位到的页面元素,点击
• expect().toHaveTitle()
断言title内容
• expect().toBeVisible()
断言文本内容可见
小结:
1,不需要手动设置等待或调用 sleep
。
2,只需关注操作和断言,Playwright 会自动处理复杂细节
常用的api
介绍与技巧
playwright
提供了比较丰富的api
,
结合我自己的体会,从最简单test case
代码构成来看
大概划分
test api
导航 api
定位 api
交互 api
断言 api
就是
test api
开启一个test case
- 在
导航 api
中实现访问某个URL
- 在
定位 api
中定位某个页面元素
- 在
交互 api
中实现元素操作
- 在
断言 api
中给出结果断言
test api
test.describe
:描述一组用例
要组织一个测试模块,可以用describe
把一组test
包括进来
test.describe('two tests', () => {
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
解释如下
• test.describe()
,定义的测试模块,包括了2个test
• test
之间是互相隔离的,执行上不存在先后次序,可同时执行
• two tests
作为title
参数会出现在测试报告
中每一个test
中
常见技巧,有时候,代码开发和调试过程中,如单独执行
、跳过执行
、随后调试
可考虑以下api
:
test.describe.only('仅执行该组', () => {
test('example', async ({ page }) => {
// This test will not run
});
});
test.describe.skip('忽略改组', () => {
test('example', async ({ page }) => {
// This test will not run
});
});
test.describe.fixme('待修改组', () => {
test('example', async ({ page }) => {
// This test will not run
});
});
test
:描述单个用例
一个test
对应一个用例,即test case
• test(title, callback)
import { test, expect } from '@playwright/test';
test('测试用例', async ({ page }) => {
await page.goto(..);
});
解释如下
test()
是一个方法,接收2个参数- 第1个参数是字符串,
测试用例
- 第2个参数是
callback函数
,即async ({ page }) => {}
page
是一个上下文参数,后面具体说async
是异步
的简写,这里是个异步调用
await
是async await
简写,等待异步方法执行完成
test
也有describe
相类似的方法
test.only('仅执行用例', async ({ page }) => {
// ...
});
test.skip('跳过该用例', async ({ page }) => {
// ...
});
test.fixme('跳过该用例', async ({ page }) => {
// ...
});
导航 api
page.goto
:导航到页面
await page.goto('https://baidu.com/');
前进后退
// 回退
await page.goBack();
// 前进
await page.goForward();
定位 api
在playwright
中可以说非常重要,甚至可以说,决定了自动化是否顺利实施
选用什么定位方法直接决定了定位是否成功
定位策略
结合自己使用下来体会
playwright
建议的策略
1. 优先getBy
方法:比如这些
getByRole()
getByText()
getByPlaceholder()
getByAltText()
getByTitle()
getByTestId()
2. 其次locator
方法
page.locator()
3. 多元素处理
locator().first()
locator().last()
locator().nth()
locator().all()
按钮定位
await page.getByRole('button', { name: '登录' }).click();
文本定位
await expect(page.getByText('Welcome')).toBeVisible();
小技巧
精准匹配
await expect(
page.getByText('导航', { exact: true }))
.toBeVisible();
正则匹配
await expect(
page1.getByText(/^共 \d{1,3} 条$/))
.toBeVisible();
输入框定位
await page
.getByPlaceholder('name@example.com')
.fill('playwright@microsoft.com');
图片定位
await page
.getByAltText('logo')
.click();
css定位
await page.locator('.content);
id定位
await page.locator('#su);
交互 api
点击
await page
.getByAltText('logo')
.click({delay: 100});
文本输入
await page
.getByPlaceholder('请输入')
.fill('end2end demo');
断言 api
expect
用来写断言
那断言内容呢
除通用断言外
主要是页面元素的可见性
页面断言
// 标题
await expect(page).toHaveTitle('');
// url
await expect(page).toHaveURL(/.*\/login/);
// 按钮
await expect(
page1.getByRole('button', { name: '已申请' }))
.toBeVisible();
// 文本
await expect(page1.getByText(/没有数据/))
.toBeVisible();
通用断言
// 数值
expect(responseCode).toBe(200);
expect(resBody).toHaveProperty('access_token');
// 字符串
expect(resBody).toContain('时空数据')
小结
1. 利用codege
快速生成代码是个比较好的开始
2. 运用playwright
提供的api
接口重新组织测试用例,其中test.describe
用于描述测试模块
,test
则对应到测试用例
,还可以用test.only
,test.describe.skip
来调整用例执行,熟悉这些api
可以迅速掌握手写代码
3. 定位策略是UI自动化的一个关键点,推荐的定位次序为:getBy方法
> locator方法
,如果返回有多个元素,可以用locator().first()
, locator.last()
, locator.nth(i)
. locator.all()
等精确定位
4. 页面交互最常见click()
、fill()
,也可以带参数,如click({delay:100})
实现延迟效果
5. 断言expect()
, 比较常见的是元素可见,expect().toBeVisible()
暂无评论内容