为什么选择Playwright?
在开始之前,你可能想知道为什么选择Playwright而不是其他测试框架。我最初接触Playwright是因为它出色的跨浏览器支持——它同时支持Chromium、Firefox和WebKit内核,这意味着你可以用一套代码测试Chrome、Firefox和Safari。更重要的是,它的自动等待机制让测试脚本更加稳定,不需要像以前那样到处添加sleep语句。
我使用Playwright已经有一年多时间,在实际项目中它确实大大减少了因页面加载时间不稳定导致的测试失败。下面我将带你从零开始搭建环境,并编写第一个真正的测试脚本。
环境搭建:一步步来
- 安装Node.js
Playwright基于Node.js,所以首先需要安装Node.js环境。我建议使用Node.js 16或更高版本。
检查Node.js是否安装
node --version
如果未安装,访问Node.js官网下载安装包
https://nodejs.org/
安装完成后,我习惯创建一个专门的目录来管理测试项目:
mkdir playwright-tutorial
cd playwright-tutorial
- 初始化项目并安装Playwright
初始化npm项目(一路按回车使用默认值即可)
npm init -y
安装Playwright
npm install playwright
或者如果你想要TypeScript支持
npm install playwright @types/node @typescript-eslint/eslint-plugin --save-dev
安装过程可能需要几分钟,因为Playwright会下载它需要的浏览器二进制文件。我建议喝杯咖啡等待一下——第一次安装时它会下载三个浏览器(Chromium、Firefox和WebKit),大约需要200-300MB磁盘空间。
- 验证安装
创建一个简单的验证脚本 check-installation.js:
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://www.example.com');
console.log('页面标题:', await page.title());
awaitnewPromise(resolve => setTimeout(resolve, 3000)); // 等待3秒查看效果
await browser.close();
})();
运行这个脚本:
node check-installation.js
如果你看到一个浏览器窗口打开并显示example.com,恭喜你!环境搭建成功。
配置编辑器(可选但推荐)
我个人使用VS Code,并且推荐安装这些扩展:
Playwright Test for VSCode(官方扩展)
Code Spell Checker(避免拼写错误)
在项目根目录创建 .vscode/launch.json 文件可以方便调试:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "运行Playwright测试",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand"]
}
]
}
编写第一个真正的测试脚本
现在进入有趣的部分!让我们编写一个实际的测试场景:测试百度搜索功能。
创建文件 first-test.js:
const { chromium } = require('playwright');
describe('百度搜索测试', () => {
let browser;
let page;
// 每个测试用例之前运行
beforeEach(async () => {
browser = await chromium.launch({
headless: false, // 设置为true可以在后台运行
slowMo: 500// 放慢操作速度,方便观察
});
page = await browser.newPage();
await page.goto('https://www.baidu.com');
});
// 每个测试用例之后运行
afterEach(async () => {
await browser.close();
});
it('应该能够搜索关键词并显示结果', async () => {
// 定位搜索框并输入内容
const searchInput = await page.$('#kw');
await searchInput.type('Playwright自动化测试');
// 点击搜索按钮
const searchButton = await page.$('#su');
await searchButton.click();
// 等待搜索结果加载
await page.waitForSelector('.result');
// 获取第一个结果标题
const firstResult = await page.$('.c-container h3 a');
const title = await firstResult.textContent();
console.log('第一个搜索结果:', title);
// 简单的断言
expect(title).toContain('Playwright');
});
it('应该能够处理无结果的情况', async () => {
// 输入一个不太可能存在的搜索词
const searchInput = await page.$('#kw');
await searchInput.type('asdfghjkl1234567890特殊测试词');
const searchButton = await page.$('#su');
await searchButton.click();
// 等待无结果提示出现
await page.waitForSelector('.content_none');
const noResultText = await page.textContent('.content_none');
expect(noResultText).toContain('没有找到');
});
});
// 运行测试
(async () => {
const { runTests } = require('./test-runner');
await runTests();
})();
让测试更健壮:最佳实践
- 使用选择器的最佳方式
我刚开始用Playwright时,犯过过度依赖CSS选择器的错误。实际上,Playwright提供了更好的定位方式:
// 不推荐 - 过于脆弱
await page.click('#main > div > form > input.submit');
// 推荐 - 使用文本内容
await page.click('text=搜索');
// 推荐 - 使用data-testid属性(需要在开发时添加)
await page.click('[data-testid="search-button"]');
// 推荐 - 使用角色定位
await page.click('button:has-text("Submit")');
- 处理弹窗和导航
实际测试中经常遇到弹窗和页面跳转:
// 处理弹窗
page.on('dialog', async dialog => {
console.log(弹窗消息: ${dialog.message()});
await dialog.accept(); // 或 dialog.dismiss()
});
// 等待新窗口打开
const [newPage] = awaitPromise.all([
page.waitForEvent('popup'),
page.click('a[target="_blank"]')
]);
// 处理iframe
const frame = page.frame({ name: 'login-frame' });
await frame.fill('#username', 'testuser');
- 添加截图和视频功能
调试时截图非常有用:
it('失败时截图', async () => {
try {
// 测试代码...
} catch (error) {
// 保存截图和HTML
await page.screenshot({ path: 'error-screenshot.png', fullPage: true });
await page.content().then(html => {
require('fs').writeFileSync('error-page.html', html);
});
throw error;
}
});
常见问题解决
在我使用Playwright的过程中,遇到过这些问题:
浏览器启动失败:通常是因为杀毒软件阻止,尝试关闭杀毒软件或添加到白名单。
元素找不到:最常见的问题。使用 page.waitForSelector() 或 page.waitForFunction() 等待元素出现。
跨域问题:Playwright默认禁用Web安全,但如果仍有问题,可以尝试:
await page.goto('https://example.com', {
waitUntil: 'networkidle'
});
中文输入问题:使用 page.type() 而不是 page.fill() 来输入中文。
进阶:整合测试框架
虽然我们可以自己写测试运行逻辑,但使用成熟的测试框架更方便。我推荐Jest或Playwright Test(Playwright自带的测试运行器)。
安装Playwright Test:
npm install @playwright/test
然后创建 tests/example.spec.js:
const { test, expect } = require('@playwright/test');
test('基础测试', async ({ page }) => {
await page.goto('https://www.baidu.com');
await page.type('#kw', 'Playwright');
await page.click('#su');
await page.waitForSelector('.result');
const title = await page.title();
expect(title).toContain('Playwright');
});
运行测试:
npx playwright test
总结
到现在为止,你已经成功搭建了Playwright测试环境,并编写了第一个自动化测试脚本。我建议从简单的页面开始练习,逐步尝试更复杂的交互场景。
记住,好的自动化测试不仅仅是让脚本运行起来,还要考虑可维护性、稳定性和可读性。给选择器起有意义的名称,添加清晰的注释,处理好等待和异常——这些习惯会让你的测试代码更加健壮。
下一步,你可以尝试:
测试一个登录流程
处理文件上传下载
模拟移动设备
集成到CI/CD流程中
每个步骤都会让你对Playwright有更深的理解。开始你的自动化测试之旅吧!