news 2026/10/21 2:32:54

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Playwright Java WEB UI 自动化实现框架与逻辑

目录

一、环境搭建:

二、框架搭建

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

java -version 探测是否配置成功,显示版本号为配置成功

maven3

mvn -v探测是否配置成功,显示版本号为配置成功

二、框架搭建

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/ # 冒烟

分层约定:

层

类

职责

配置层

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(); } } }

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

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

执行方式:

指定浏览器执行:

多浏览器执行:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 2:32:53

Java 多线程安全:从 synchronized 到 volatile 的完整实战指南

导语&#xff1a;多线程编程中&#xff0c;线程安全问题往往是并发开发的第一道门槛。本文从线程调度随机性、共享变量修改、原子性等根源问题出发&#xff0c;系统讲解 synchronized 的多种写法、可重入锁、死锁的四个必要条件&#xff0c;以及 volatile 如何解决内存可见性与…

作者头像 李华
网站建设 2026/10/21 2:32:23

远程多路监控集成技术指南:多画面分屏与轮播的实现方案

痛点引入 在视频监控系统的集成开发中&#xff0c;多路视频流的远程并发查看是一个核心且高频的需求。用户通常期望在一个界面中同时预览多个摄像头画面&#xff0c;并支持多画面分屏显示与定时轮播切换。然而&#xff0c;在实际工程落地过程中&#xff0c;开发者往往面临以下技…

作者头像 李华
网站建设 2026/10/21 2:32:23

事件相机_基于异步轨迹的结构和运动的线性n点求解器_ICCV 2025

ICCV 2025 的论文 《A Linear N-Point Solver for Structure and Motion from Asynchronous Tracks》 :利用具有独立时间戳的二维点轨迹,结合角速度信息,统一估计相机平移速度与三维点结构。 这里要区分两件事: ETAP / KLT: 负责提供点轨迹。 N-Point Solver: 利用轨迹、…

作者头像 李华
网站建设 2026/10/21 2:32:20

大一C语言学习记录-3

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/21 2:31:25

开源项目停更≠死掉:判断维护状态与应对冻结代码的实用策略

如果你最近在Gitee上找开源组件&#xff0c;大概率会遇到一种情况&#xff1a;翻看一个仓库的提交记录&#xff0c;最后一次commit写的是2023年6月&#xff0c;然后又翻了几个仓库&#xff0c;情况惊人地相似。这不是某个项目的特例&#xff0c;而是一整片区域内的项目都停在了…

作者头像 李华