playwright 元素定位检查,自动登录
在页面交互操作中,常常会根据某元素是否存在来决定下一步的操作任务。本文总结了项目中使用Playwright比较常用的方法和技巧。
使用
page.isVisible
用 page.isVisible 检查页面上的元素是否可见。如果可见,则该函数返回 true;否则返回 false。参考下面的例子:
// 已经登录就截图,否则就去登录页
if ( await page.isVisible("text='个人中心'") ) {
await page.screenshot({ path: 's1.png' });
} else {
await e2eLogin(page, 'username', 'password');
await expect(page.getByText('个人中心')).toBeVisible();
await page.context().storageState({ path: 'user.json' });
}
使用
locator.waitFor
await page
.locator('...')
.waitFor({ timeout: 5000 })
.catch(() => {});
if (await page.locator('...').isVisible()) {
// ...
}
使用
locator+条件
const myElement = page.locator('#elem-id')
if (await myElement.isVisible()) {
await myElement.click()
}
使用
locator.or

考虑如下场景:
你想要单击 "新邮件" 按钮,但有时会显示安全设置对话框。在这种情况下,你可以等待 "新邮件" 按钮或对话框并进行相应操作
const newEmail = page.getByRole('button', { name: 'New email' });
const dialog = page.getByText('Confirm security settings');
await expect(newEmail.or(dialog)).toBeVisible();
if (await dialog.isVisible())
await page.getByRole('button', { name: 'Dismiss' }).click();
await newEmail.click();
使用测试生成器
-
断言可见性工具生成expect(locator).toBeVisible() -
断言值工具生成expect(locator).toHaveValue() -
断言文本工具生成expect(locator).toContainText()
参考如下示例:
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page
.goto('https://playwright.nodejs.cn/');
await page
.getByRole('link', { name: 'Get started' })
.click();
await expect(page
.getByLabel('Breadcrumbs')
.getByRole('list'))
.toContainText('Installation');
await expect(page
.getByLabel('Search'))
.toBeVisible();
await page
.getByLabel('Search')
.click();
await page
.getByPlaceholder('Search docs')
.fill('locator');
await expect(page
.getByPlaceholder('Search docs'))
.toHaveValue('locator');
});
-
page.isVisiable适合判断element是否存在 -
locator+条件是另外一种实现方法 -
page.waitFor({timeout: 1000})可指定等待时间 -
locator.or更适合出现的元素2选1这样的场景 -
断言生成器也提供了录制代码可视化断言方法
在web自动化测试实践中,常常遇到登录相关的问题:
-
怎样实现自动化登录?
-
验证码怎么处理?如何自动化?
-
多因素验证,如需要输入手机短信验证码怎么办?
-
微信扫描二维码能自动化吗?
-
如何记住登录状态?
下面将分享如何制定适当的测试策略,并使用Playwright实现登录保持状态,在后续自动化测试使用,从而加快后续自动化测试,并以b站登录为例进行说明。
2. 制定登录测试验证策略
鉴权,即成功登录web往往是验证用户合法性第一步。从自动化测试角度看
-
实现自动化登录往往是第一步
-
不同场景测试都去执行登录又显得很繁琐
-
如何实现 “一次登录并保持登录” 状态?
从网站开发角度看
-
最简单的登录功能实现一般包括:
用户名、密码、提交按钮 -
出于现实安全性考虑,往往会增加
验证码环节,或者 -
多因素认证,例如通过手机短信验证码,或者 -
支持通过
app扫码,微信二维码扫码登录 等
从产品开发迭代发布周期来看
-
在正式发布的线上环境,
手工测试验证依然是必不可少的,针对验证码、手机短信验证、app扫码登录、微信扫码登录等场景功能验证依然需要手工方式,基于实现成本,一般不建议完全从自动化角度考虑 -
在迭代开发的测试环境、开发环境,可以和产研团队协商,从方便自动化测试角度考虑,可以设定特殊的
测试账号或者绕过鉴权步骤,或者简化验证手段等等 -
结合
自动化测试(测试环境为主)、手动测试(线上环境为主),针不同目标采用不同测试策略
以上,验证码、二维码 对于自动化都是相对比较困难的问题。通过制定手工测试结合自动化测试不同策略,可以将不同的登录问题区分开来。
无论手动输入验证码登录,扫描二维码登录,或是自动登录,完成成功鉴权后,如果能把对应的浏览器状态保持下来,在后续测试中复用,就可以免重复登录,实现一次登录并保持以加快后续测试执行速度。
在开始使用Playwrgith保存和读取浏览器状态前,先看下浏览器数据保存机制。
3. 数据是如何在浏览器保存的
以b站为例,登录成功后,在后台可以看到cookie、本地存储、会话存储

Cookies、localStorage、sessionStorage都是用于在浏览器中存储数据的机制,但它们在存储方式、生命周期和使用场景上有一些区别。
Cookies:
-
存储方式: 使用
Cookies存储的数据可以设置过期时间,也可以在浏览器关闭后仍然保留。 -
• 生命周期: 可以设置过期时间,可以在浏览器关闭后仍然保留。
-
• 使用场景: 适合存储需要在不同会话之间共享的数据,比如 用户登录状态。
localStorage:
-
存储方式: 使用
localStorage存储的数据会一直存在,除非被主动删除或网站清除浏览数据。 -
• 生命周期: 永久性存储,除非手动删除或网站清除。
-
• 使用场景: 适合存储不会过期的数据,比如用户偏好设置。
sessionStorage:
-
存储方式: 使用
sessionStorage存储的数据仅在当前会话期间有效,关闭标签页或浏览器后会被清除。 -
• 生命周期: 会话期间有效,关闭标签页或浏览器后清除。
-
• 使用场景: 适合存储临时性数据,比如表单数据,在用户关闭标签页后不再需要。
可以针对具体情况分析状态信息如何存储,这个对后面的复用浏览器状态有用。多数网站的登录信息存储在cookie中,也有少数采用会话存储方式。
4. Playwright中如何复用浏览器状态
4.1 本地cookie保存
Playwright保存浏览器状态,参考下面的代码:
// 保存到文件
await page.context().storageState({ path: '.auth/user.json' });
以b站来说,登录成功以后,身份验证信息保存在cookie。
4.2 本地cookie复用
在上一步将cookie保存到文件后,复用就非常简单了,只需要从browser对象生成page对象时候指定storageState为之前保存的文件即可,参考代码:
const page = await browser.newPage(
{ storageState:'.auth/user.json'} );
//已复用登录后的身份信息,无需重复登录
await page.goto('https://space.bilibili.com/');
进一步,如果需要整个项目复用的话,需有修改配置文件 playwright.config.ts
export default defineConfig({
/* Configure projects for major browsers */
projects: [
{
name: 'Microsoft Edge',
use: {
...devices['Desktop Edge'] ,
// 复用auth信息
storageState: '.auth/user.json',
},
},
],
});
主要就是 use 这里
4.3 会话存储sessionStorage保存
根据Playwright文档的说法,上面cookie复用的方法可以搞定多数基于本地存储的身份验证了。
但是也有例外
出于安全性等考虑,有些网站的身份验证信息是基于sessionStorage的,用上面的办法保留下来的文件内容是空。并且Playwright也不提供用于持久化会话存储的 API,该如何复用呢?已经验证过下面的例子可用,来自于官网
Authentication | Playwright
const sessionStorage = await page.evaluate(() => JSON.stringify(sessionStorage));
fs.writeFileSync('.auth/session.json', JSON.stringify(sessionStorage), 'utf-8');
4.4 会话存储sessionStorage复用
从文件session.json读取身份验证信息,并在测试中复用:
test.beforeEach(async ({ page }) => {
const sessionStorage = JSON.parse(fs.readFileSync('.auth/session.json', 'utf-8'));
await context.addInitScript(storage => {
for (const [key, value] of Object.entries(storage))
window.sessionStorage.setItem(key, value);
}, sessionStorage); });
5. b站登录例子
-
• 需求: 实现b站登录后,在后续测试中可以复用登录信息
-
• 思路: 简单分析后,b站采用
cookie保存登录信息,那么可以考虑将cookie内容保存下来,在后续case复用即可;至于登录部分,无论方式是验证码还是app扫码,出于实现成本和稳定性角度,考虑手动方式会更合理 -
• 问题: 如何结合
自动化测试和手动测试配合完成? -
• 解决: Playwright提供了
timeout参数,可以设定合理的值比如15秒留给手动操作
5.1 登录case
采用录制(npx playwright codegen https://bilibili.com)等方式生成如下测试case bilibili.spec.ts
import { test, expect, browser } from '@playwright/test';
const authFile = '.auth/user.json';
test('1.保存登录信息', async ({ page }) => {
await page.goto('https://www.bilibili.com/');
//扫码登录..
await expect(page.getByText('登录成功', { exact: true })).toBeVisible({timeout: 15000});
await page.context().storageState(
{ path: authFile });
await page.close();
});
test('2.记住登录', async ({ browser }) => {
const page = await browser.newPage(
{ storageState:authFile } );
await page.goto('https://space.bilibili.com/');
await expect(page).toHaveTitle(/个人主页/);
await page.close();
await browser.close();
});
说明如下:
-
• 第1个
test在b站登录成功后,将浏览器状态保存到.auth/user.json文件中。要注意的是,扫码部分需要配合人工在手机上操作,也可以输入用户名密码完成 -
• 以上登录操作需要在15m成功完成,否则test会失败,
timeout:15000,这里也可根据情况调整时间 -
• 第2个
test访问b站个人空间,不需要扫码或输入用户名,验证身份信息可以复用
5.2 配置文件
bilibili.spec.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: false,
reporter: 'html',
use: {
video: 'on',
locale: 'zh-cn'
},
projects: [
{
name: 'Microsoft Edge',
use: {
...devices['Desktop Edge'] ,channel: 'msedge',
//auth
storageState: '.auth/user.json',
},
},
],
});
-
说明如下
-
1.
projects配置storageState -
2.
testDir设置为./tests目录 -
3.
use配置了video为on,locale为zh-cn
5.3 video截屏
-
• test1 - 保存登录信息
-
说明如下
-
1.
projects配置storageState -
2.
testDir设置为./tests目录 -
3.
use配置了video为on,locale为zh-cn
总结:
-
记住登录状态,在后续测试中复用能加快自动化测试,提高执行效率
-
• 浏览器存储身份验证信息,多数位于
cookie中,也有sessionStorage -
•
Playwright中storageState可以存储和读取身份验证信息,通常保存在cookie,比如一些token;sessionStorage也可以存储,可以用fs.write保存 -
• 配置文件
playwright.config.ts可设置项目参数storageState: '.auth/user.json'来复用经过身份验证的状态,从而免去重复登录 -
• 合理制定自动化测试策略,比如在
测试环境多考虑一些自动化测试手段,乃至要求研发侧做适当改造从而加快自动化测试都是有必要的,而线上环境多考虑一些手动测试覆盖
更多推荐



所有评论(0)