目录
一、环境搭建:
二、框架搭建
1. 框架定位
2. 工程结构
3. 浏览器生命周期
4. 配置逻辑
5. 登录态:为什么不用 UI 登录
6. 样例用例执行逻辑(CreateXXAccountTest)
6.1 执行时序
6.2 页面操作明细
6.3 和 Page Object 示例的差异
7. 失败处理与可观测性
8. 如何运行这条用例
9. 再写一条业务用例的推荐步骤
10. 当前局限
三、实战-怎么快速写一个用例
一、环境搭建:
框架:playwright+testng+java+Allure
环境搭建与配置:
安装:idea、jdk21、maven3.x
配置环境变量:
工具 | 下载与安装 | 系统环境变量配置 | 其他设置 | |
idea | 官网下载即可 | 无 | 配置jdk:以下几个位置设置jdk版本 配置maven:file->settings | |
jdk21 |
| |||
maven3 |
|
二、框架搭建
1. 框架定位
这是一套 Maven + JDK 17 + TestNG + Playwright Java 的 Web UI 自动化框架。
设计目标:
浏览器生命周期统一管理,用例之间状态隔离
配置与代码分离,本地 / CI 可用不同环境
业务用例只写页面操作和断言,不自己启动浏览器
失败可追溯:日志、截图、Playwright Trace、失败重试
需要登录的业务页,用
auth.json(storageState)复用登录态,避开验证码
核心依赖:Playwright1.55.0、TestNG7.10.2、AssertJ、Allure TestNG、SLF4J + Log4j2。
2. 工程结构
playwright_java_demo
├── pom.xml
├── auth.json # 登录态(cookie + localStorage),由 GenAuthManual 生成
├── src/main/java/com/playauto
│ ├── config/EnvConfig.java # 读取 config*.properties,支持 -D 覆盖
│ ├── driver/PlaywrightManager.java # Playwright / Browser / Context / Page
│ ├── pages/ # Page Object(BasePage + 业务页)
│ ├── common/ScreenshotHelper.java # 失败截图
│ └── listener/ # 日志 / 截图 / 失败重试
├── src/main/resources
│ ├── config.properties # 默认环境(当前指向 xx服务 测试环境)
│ ├── config-dev.properties
│ ├── config-test.properties
│ └── log4j2.xml
└── src/test/java/com/playauto
├── base/BaseTest.java # 用例基类
└── cases
├── yewucase_package/ # 业务用例(xxxx)
├── demo/ # 示例用例(百度、TodoMVC)
└── smoke/ # 冒烟
分层约定:
层 | 类 | 职责 |
配置层 |
| 浏览器、超时、headless、base.url |
驱动层 |
| 启动/关闭浏览器,创建 Context,注入 storageState |
基类层 |
| TestNG 生命周期,暴露 |
页面层 |
| 页面操作封装(POM) |
用例层 |
| 编排步骤,不做驱动管理 |
监听层 | TestNG Listener | 日志、失败截图、失败重试 |
3. 浏览器生命周期
官方 Playwright + TestNG 模型:
每个测试类启动一次 Browser(
@BeforeClass)每个
@Test方法新建独立的BrowserContext+Page(@BeforeMethod)方法结束关闭 Context(
@AfterMethod)类结束关闭 Browser(
@AfterClass)
这样每条用例的 cookie、localStorage、登录态互不影响。Playwright 对象非线程安全,套件并行只能parallel="classes",不能parallel="methods"。
PlaywrightManager用ThreadLocal保存 Playwright / Browser / Context / Page,避免跨线程串用。
创建 Context 时还会:
设置视口、忽略 HTTPS 错误、语言
zh-CN、时区Asia/Shanghai可选加载
auth.json作为storageState注入脚本隐藏
navigator.webdriver按配置开启 Trace / 录像
设置默认动作超时、导航超时
4. 配置逻辑
EnvConfig启动时加载:
-Denv=dev|test→config-dev.properties/config-test.properties未指定 →
config.properties任意 key 都可用 JVM 参数覆盖,例如
-Dheadless=false
当前默认配置要点:
base.url:https://域名url/#/loginbrowser=chrome(走本机 Chrome channel)headless=falsetimeout.ms=15000,navigation.timeout.ms=30000retry.count=1失败截图、失败 Trace 开启
5. 登录态:为什么不用 UI 登录
XXLoginTest走登录页时需要填图片验证码,自动化不稳定。框架采用 Playwright 官方 storageState 方案:
运行
com.playauto.cases.xx.GenAuthManual弹出浏览器,人工完成登录(含验证码)
控制台回车后,把 cookie + localStorage 写到项目根目录
auth.json业务用例在创建 Context 时加载该文件,打开业务页时已是登录态
BaseTest提供钩子,子类按需覆盖:
protected Path storageStatePath() {
return null; // 默认不加载登录态
}
CreateXXAccountTest覆盖为:
@Override
protected Path storageStatePath() {
return Paths.get("auth.json");
}
加载时机在page.navigate()之前。如果文件不存在,直接失败并提示先跑GenAuthManual。token 过期后需重新生成auth.json。
注意:auth.json含登录凭证,不要提交到 Git。
6. 样例用例执行逻辑(CreateXXAccountTest)
目标:在代理商账户页新建一个代理商账户。
页面:https://域名/#/页面url
6.1 执行时序
TestNG 启动 CreateXXAccountTest
→ @BeforeClass launchBrowser()
Playwright 启动 Chrome(有头)
→ @BeforeMethod createContextAndPage()
读取 storageStatePath() = auth.json
用 cookie/localStorage 创建 BrowserContext
新建 Page,赋给 this.page
→ @Test shouldCreateXXAccount()
1. navigate 到XX账户页(此时已登录)
2. 点「新建代理商账户」
3. 填xx信息
4. 选「返佣模式」
5. 填登录用户信息
6. 点「确定」
→ 失败则 FailureArtifactListener 截图
PlaywrightManager 保存 Trace
→ @AfterMethod 关闭 Context
→ @AfterClass 关闭 Browser
6.2 页面操作明细
定位策略以 ARIA Role + 可见名称 为主(getByRole/getByText),避免脆弱 CSS。
步骤 | 操作 | 数据 |
1 | 打开xx账户页 | 见 PAGE_URL |
2 | 点击按钮「新建xx账户」 | — |
3 | 填写「xx名称*」 | xxx |
4 | 填写「账户联系人*」 | 自动创建 |
5 | 填写「联系人电话*」 | xxxx |
6 | 填写「联系人邮箱*」 | xxxx |
7 | 点击「xx模式」 | — |
8 | 填写「用户名称*」 | xx |
9 | 填写「邮箱*」(exact,避免和联系人邮箱混淆) | xx |
10 | 填写「登录密码*」 | xx |
11 | 填写「确认登录密码*」 | xx |
12 | 点击按钮「确定」 | — |
「邮箱*」使用setExact(true),是因为页面上同时存在「联系人邮箱*」和「邮箱*」,精确匹配才能点到登录邮箱。
6.3 和 Page Object 示例的差异
TodoMvcTest走标准 POM:页面操作在TodoMvcPage,用例只编排 + 断言。
CreateXXAccountTest目前把录制步骤写在测试类里,便于快速落地业务流。后续建议抽成XXAccountPage,用例里只保留:
打开页面
调用
createXX(...)断言创建成功(toast / 列表出现新账户)
当前用例还没有断言,属于流程冒烟;要做成稳定回归,需要补成功提示或列表校验。
7. 失败处理与可观测性
TestNG 监听器在src/test/resources/suites/testng.xml中注册:
监听器 | 作用 |
| 套件/用例开始、通过、失败、跳过日志 |
|
|
| 给所有 |
失败且trace.on.failure=true时,Trace 存到target/traces/{类名.方法名}.zip。查看:
mvn exec:java -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="show-trace target/traces/CreateXXAgencyAccountTest.shouldCreateAgencyAccount.zip"
Allure 结果目录:target/allure-results。
8. 如何运行这条用例
先保证根目录有未过期的auth.json。没有则先运行GenAuthManual。
单独跑新建代理商:
mvn test -Dtest=com.playauto.cases.xx服务简称.CreateXXAccountTest
IDEA:打开工程 → 选 JDK 17+ → 在CreateXXAccountTest上右键 Run。
当前testng.xml还没挂上 xx服务 用例,全量mvn clean test不会跑到它。要进套件,在 xml 里加:
<class name="com.playauto.cases.xx服务简称.CreateXXAccountTest"/>
9. 再写一条业务用例的推荐步骤
若页面需登录:确认
auth.json有效,或重新跑GenAuthManual新建测试类,继承
BaseTest覆盖
storageStatePath()指向auth.json@Test中page.navigate(业务URL),再用getByRole操作稳定后把操作抽到
pages下的 Page Object,用例只留编排和断言需要进日常回归时,把类名加入对应 TestNG suite
10. 当前局限
登录依赖人工生成的
auth.json,过期后要重录CreateXXAccountTest无结果断言,重复执行可能因账户名/邮箱已存在而失败测试数据写死在代码里,后续可抽到 properties / 数据驱动
类名不要再用
Test,会和 TestNG 的@Test注解冲突(本用例已改为CreateXXAccountTest
三、实战-怎么快速写一个用例
前置录制脚本信息:
页面测试case脚本快速录制:
codegen 录制!先手动在浏览器点一遍业务,直接生成 locator 代码,省去手写定位器,写用例速度最快。
打开 cmd 执行录制命令(需要在项目根目录下执行--根目录下有pom.xml文件),直接录操作,复制生成的代码到用例里面改。
直接执行会报以下错误:mvn exec:java -Dexec.mainClass="com.microsoft.playwright.CLI" -Dexec.args="codegen 项目xiangmuxiang根目录"
PowerShell 对 maven 的-Dxxx=value参数解析异常,当 value 带空格时,-D被吞掉,maven 收到参数变成.args="codegen https://xxx",于是 maven 误以为这是插件前缀,报No plugin found for prefix '.args=codegen https'。
解决:PowerShell 用双引号包裹整个‑D 参数(前面加反引号 )
mvn exec:java "-Dexec.mainClass=`"com.microsoft.playwright.CLI`"" "-Dexec.args=`"codegen https://测试域名/#/login`""如果录制的时候想用本机 Chrome(不是 playwright 自带浏览器)
录制命令追加参数--executable-path指定本机 chrome 路径
mvn exec:java "-Dexec.mainClass=`"com.microsoft.playwright.CLI`"" "-Dexec.args=`"codegen --executable-path='C:\Users\EDY\AppData\Local\Google\Chrome\Application\chrome.exe' https://测试域名/#/login`""重点坑:codegen 浏览器窗口大小≠视口 (viewport)!就算你手动拉大浏览器窗口,页面布局依旧受内部 viewport 控制;网页是响应式,视口小页面就切到移动端布局,菜单 / 侧边栏直接消失,内容展示不全,录制出来的 locator 全部不对Playw...。
✅解决:启动 codegen 时显式设置大视口(Java mvn 命令)
mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="codegen --viewport-size='1920,1080' --target=java"命令行各种坑,执行以下脚本录制
src/test/java/com/playauto/cases/Record.java URL替换成要测试的页面链接
执行以下脚本录制
import com.microsoft.playwright.*; //手动录制测试脚本 public class Record { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType.LaunchOptions launchOptions = new BrowserType.LaunchOptions(); launchOptions.setArgs(java.util.List.of("--disable-gpu")); launchOptions.setHeadless(false); Browser browser = playwright.chromium().launch(launchOptions); BrowserContext context = browser.newContext( new Browser.NewContextOptions().setViewportSize(null) // .setViewportSize(1920, 728)//关闭页面大小设置,页面元素会展示不全 ); Page page = context.newPage(); // page.navigate("要测试的页面url地址"); page.navigate("要测试的页面url地址"); // ↓暂停,此时自动弹出Playwright‑Inspector拾取窗口! page.pause(); } } }直接去要测试的页面上正常操作,操作完保存录制的脚本,将录制的内容只复制业务代码
将录制好的代码直接复制到用例里使用
执行方式:
指定浏览器执行:
多浏览器执行: