![图片[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()








暂无评论内容