Playwright Java WEB UI 自动化实现框架与逻辑

目录

一、环境搭建:

二、框架搭建

[1. 框架定位](#1. 框架定位)

[2. 工程结构](#2. 工程结构)

[3. 浏览器生命周期](#3. 浏览器生命周期)

[4. 配置逻辑](#4. 配置逻辑)

[5. 登录态:为什么不用 UI 登录](#5. 登录态:为什么不用 UI 登录)

[6. 样例用例执行逻辑(CreateXXAccountTest)](#6. 样例用例执行逻辑(CreateXXAccountTest))

[6.1 执行时序](#6.1 执行时序)

[6.2 页面操作明细](#6.2 页面操作明细)

[6.3 和 Page Object 示例的差异](#6.3 和 Page Object 示例的差异)

[7. 失败处理与可观测性](#7. 失败处理与可观测性)

[8. 如何运行这条用例](#8. 如何运行这条用例)

[9. 再写一条业务用例的推荐步骤](#9. 再写一条业务用例的推荐步骤)

[10. 当前局限](#10. 当前局限)

三、实战-怎么快速写一个用例


一、环境搭建:

框架:playwright+testng+java+Allure

环境搭建与配置:

安装:idea、jdk21、maven3.x

配置环境变量:

|--------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---|
| 工具 | 下载与安装 | 系统环境变量配置 | 其他设置 | |
| idea | 官网下载即可 | 无 | 配置jdk:以下几个位置设置jdk版本 配置maven:file->settings | |
| jdk21 | | java -version 探测是否配置成功,显示版本号为配置成功 | | |
| maven3 | | mvn -v探测是否配置成功,显示版本号为配置成功 | | |

二、框架搭建

1. 框架定位

这是一套 Maven + JDK 17 + TestNG + Playwright Java 的 Web UI 自动化框架。

设计目标:

  • 浏览器生命周期统一管理,用例之间状态隔离

  • 配置与代码分离,本地 / CI 可用不同环境

  • 业务用例只写页面操作和断言,不自己启动浏览器

  • 失败可追溯:日志、截图、Playwright Trace、失败重试

  • 需要登录的业务页,用 auth.json(storageState)复用登录态,避开验证码

核心依赖:Playwright 1.55.0、TestNG 7.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/ # 冒烟

分层约定:

|-----|-----------------------------|-------------------------------------|
| 层 | 类 | 职责 |
| 配置层 | EnvConfig | 浏览器、超时、headless、base.url |
| 驱动层 | PlaywrightManager | 启动/关闭浏览器,创建 Context,注入 storageState |
| 基类层 | BaseTest | TestNG 生命周期,暴露 page |
| 页面层 | BasePage 及子类 | 页面操作封装(POM) |
| 用例层 | CreateAgencyAccountTest 等 | 编排步骤,不做驱动管理 |
| 监听层 | 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 启动时加载:

  1. -Denv=dev|test → config-dev.properties / config-test.properties

  2. 未指定 → config.properties

  3. 任意 key 都可用 JVM 参数覆盖,例如 -Dheadless=false

当前默认配置要点:

  • base.url:https://域名url/#/login

  • browser=chrome(走本机 Chrome channel)

  • headless=false

  • timeout.ms=15000,navigation.timeout.ms=30000

  • retry.count=1

  • 失败截图、失败 Trace 开启

5. 登录态:为什么不用 UI 登录

XXLoginTest 走登录页时需要填图片验证码,自动化不稳定。框架采用 Playwright 官方 storageState 方案:

  1. 运行 com.playauto.cases.xx.GenAuthManual

  2. 弹出浏览器,人工完成登录(含验证码)

  3. 控制台回车后,把 cookie + localStorage 写到项目根目录 auth.json

  4. 业务用例在创建 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 中注册:

|---------------------------|---------------------------------------------------|
| 监听器 | 作用 |
| TestLogListener | 套件/用例开始、通过、失败、跳过日志 |
| FailureArtifactListener | @Test 失败后、Context 关闭前截图到 target/screenshots |
| RetryTransformer | 给所有 @Test 挂上 RetryAnalyzer,按 retry.count 重试 |

失败且 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. 再写一条业务用例的推荐步骤

  1. 若页面需登录:确认 auth.json 有效,或重新跑 GenAuthManual

  2. 新建测试类,继承 BaseTest

  3. 覆盖 storageStatePath() 指向 auth.json

  4. @Test 中 page.navigate(业务URL),再用 getByRole 操作

  5. 稳定后把操作抽到 pages 下的 Page Object,用例只留编排和断言

  6. 需要进日常回归时,把类名加入对应 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();
        }
    }
}

直接去要测试的页面上正常操作,操作完保存录制的脚本,将录制的内容只复制业务代码

将录制好的代码直接复制到用例里使用

执行方式:

指定浏览器执行:

多浏览器执行:

相关推荐
Java_AI工程师1 小时前
Spring4 / SpringBoot1.x 老项目想接入 AI?不用升级框架!3 套无痛落地方案
java·人工智能·spring boot
BBmmo1 小时前
Java Stream 的 filter 为什么看起来没运行?
java
keyipatience1 小时前
TypeScript学习(1)
前端·javascript·学习·typescript·html·css3
VimorphTech1 小时前
Java 文件缓存实战:如何避免读到未下载完成的视频?
java·spring boot
白露与泡影1 小时前
后端 Java 面试核心八股汇总|高频面试题 + 解析,覆盖基础到进阶
java·开发语言·面试
xifangge20251 小时前
基于 JavaScript 实现 CNC 数控切削参数与螺纹公差纯前端核算引擎
开发语言·前端·javascript
SL_staff2 小时前
JVS-APS 实践:用双向反馈闭环打破制造计划孤岛
java·spring cloud·全栈
wangruofeng2 小时前
2026 Web 技术选型指南,AI 时代如何选择适合项目的技术栈
前端·aigc·ai编程
\光辉岁月/2 小时前
3.包装类
java·开发语言·包装类