news 2026/9/9 19:17:15

Java 如何把 Playwright 接入 JUnit 5 测试并使用 @UsePlaywright 注入 Page 夹具?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 如何把 Playwright 接入 JUnit 5 测试并使用 @UsePlaywright 注入 Page 夹具?

Java 如何把 Playwright 接入 JUnit 5 测试并使用 @UsePlaywright 注入 Page 夹具?

【免费下载链接】playwrightPlaywright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.项目地址: https://gitcode.com/GitHub_Trending/pl/playwright

如果你的 Java 项目正在用 JUnit 5(Jupiter)做端到端测试,又不想在每个测试类里手写Playwright.create()browser.newContext()context.close()这一套生命周期代码,Playwright 提供了一组 JUnit 夹具:在测试类上加上@UsePlaywright注解,测试方法里声明Page page参数,框架就会自动初始化 Playwright、Browser、BrowserContext 和 Page,并在测试结束后清理。这个集成在文档中的标题是 “JUnit (experimental)”,于 Playwright Java 1.42 版本引入,属于实验功能(见 Release notes 与 JUnit 指南)。本文的主路径是 Maven 项目;Gradle 的差异在后面单独说明。

适用前提(来自 Installation 文档):

  • Java 8 或更高版本;
  • 操作系统为 Windows 11+ / Windows Server 2019+ / WSL、macOS 14 (Sonoma) 或更高、Debian 12/13、Ubuntu 22.04/24.04/26.04(x86-64 或 arm64);
  • 项目使用 JUnit 5,测试方法使用org.junit.jupiter.api.Test注解。

声明 Maven 依赖

Playwright 以 Maven 模块分发,最简接入方式是在pom.xmldependencies中添加一个依赖。Installation 文档 给出的完整示例如下,其中的%%VERSION%%是文档里的模板占位符,需要替换为你要使用的 Playwright 具体版本号(本仓库当前package.json中的版本为1.64.0-next,可参考仓库实际发布版本选择):

<dependencies> <dependency> <groupId>com.microsoft.playwright</groupId> <artifactId>playwright</artifactId> <version>%%VERSION%%</version> <!-- 替换为你要使用的 Playwright 版本号 --> </dependency> </dependencies>

文档同时建议配置maven-compiler-plugin3.10.1,source/target设为 1.8,并注释说明“对接口静态方法的引用要求 source level 1.8 以上”:

<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>

如果项目使用 Gradle,Test Runners 文档 给出了对应的build.gradle(Groovy)配置:依赖com.microsoft.playwright:playwright:%%VERSION%%(同样是需替换的版本占位符),repositories配置mavenCentral(),并在test块中声明useJUnitPlatform(),这样 Gradle 才会用 JUnit 5 平台执行测试。

浏览器二进制:首次运行自动下载,也可显式安装

Playwright 每个版本需要特定版本的浏览器二进制文件。按 Installation 文档,首次编译运行程序时会“下载 Playwright 包并安装 Chromium、Firefox 和 WebKit 的浏览器二进制”——即首次跑起来时浏览器会自动就位。

如果需要显式安装(例如升级 Playwright 后需要重新执行安装,见 Browsers 文档),Java 下使用 Maven 调用 Playwright CLI:

mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install"

不带参数时安装默认浏览器集;也可以指定单个浏览器,例如install webkit

mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install webkit"

想查看支持的全部浏览器,把参数换成install --help即可。这条命令只安装浏览器二进制,不影响已有测试代码。

用 @UsePlaywright 写入第一个测试

在测试类上加@UsePlaywright,测试方法的参数就“告诉 JUnit 设置对应的夹具并提供给测试方法”。JUnit 指南 的完整示例(可直接作为src/test/java下的测试类,断言即验证点):

package org.example; import com.microsoft.playwright.Page; import com.microsoft.playwright.junit.UsePlaywright; import org.junit.jupiter.api.Test; import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @UsePlaywright public class TestExample { @Test void shouldClickButton(Page page) { page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>"); page.locator("button").click(); assertEquals("Clicked", page.evaluate("result")); } @Test void shouldCheckTheBox(Page page) { page.setContent("<input id='checkbox' type='checkbox'></input>"); page.locator("input").check(); assertEquals(true, page.evaluate("window['checkbox'].checked")); } @Test void shouldSearchWiki(Page page) { page.navigate("https://www.wikipedia.org/"); page.locator("input[name=\"search\"]").click(); page.locator("input[name=\"search\"]").fill("playwright"); page.locator("input[name=\"search\"]").press("Enter"); assertThat(page).hasURL("https://en.wikipedia.org/wiki/Playwright"); } }

注意示例中三条测试方法共用同一个Browser(每个类里的测试方法共享 Browser 以优化资源),但每条测试拥有自己的BrowserContextPage,浏览器状态在测试之间是隔离的。shouldSearchWiki访问外网,如果你的环境无法访问wikipedia.org,可只保留前两个本地用例验证接入是否成功。

可用的预定义夹具

文档列出的夹具及作用(来源):

FixtureTypeDescription
pagePageIsolated page for this test run.
browserContextBrowserContextIsolated context for this test run. Thepagefixture belongs to this context as well.
browserBrowserBrowsers are shared across tests to optimize resources.
playwrightPlaywrightPlaywright instance is shared between tests running on the same thread.
requestAPIRequestContextIsolated APIRequestContext for this test run.

也就是说,方法签名里声明哪个类型,框架就注入哪个夹具;pagebrowserContextbrowserplaywrightrequest都可作为参数出现。

结果验证

文档没有给出一段固定的成功日志,验证方式就是测试断言本身:

  • assertEquals("Clicked", page.evaluate("result")):点击后页面变量result应等于"Clicked",不满足则该测试失败;
  • assertThat(page).hasURL("https://en.wikipedia.org/wiki/Playwright"):使用 Playwright 的 web-first 断言校验最终 URL;
  • assertThat(page).hasTitle(Pattern.compile("Playwright")):校验页面标题匹配正则(文档 Fixtures 章节的例子)。

用你的构建工具执行测试(Gradle 项目在test { useJUnitPlatform() }配置下通过 Gradle 的测试任务运行;Maven 走标准的test任务),测试全部通过、无失败断言,即说明@UsePlaywright夹具链路工作正常。浏览器未安装时测试会在启动浏览器环节失败,此时先执行上一节的install命令。

可选:用 OptionsFactory 定制夹具选项

默认夹具不满足时(比如要 headful 运行、或给页面/API 请求设置 baseURL),实现OptionsFactory接口并把类写进@UsePlaywright()注解即可覆盖 [BrowserType.launch] 的启动选项、Browser.newContext的上下文选项和APIRequest.newContext的选项(来源):

import com.microsoft.playwright.junit.Options; import com.microsoft.playwright.junit.OptionsFactory; import com.microsoft.playwright.junit.UsePlaywright; @UsePlaywright(MyTest.CustomOptions.class) public class MyTest { public static class CustomOptions implements OptionsFactory { @Override public Options getOptions() { return new Options() .setHeadless(false) .setContextOption(new Browser.NewContextOptions() .setBaseURL("https://github.com")) .setApiRequestOptions(new APIRequest.NewContextOptions() .setBaseURL("https://playwright.dev")); } } @Test public void testWithCustomOptions(Page page, APIRequestContext request) { page.navigate("/"); assertThat(page).hasURL(Pattern.compile("github")); APIResponse response = request.get("/"); assertTrue(response.text().contains("Playwright")); } }

要点:setHeadless(false)让浏览器带 UI 启动;setContextOption里的baseURLpage.navigate("/")这类相对路径生效;setApiRequestOptions单独控制request夹具的 baseURL。文档示例的断言是:访问/后 URL 匹配github,对request发起 GET 后响应文本包含"Playwright",可照此校验定制是否生效。

可选:并行运行多个测试类

JUnit 默认单线程顺序执行所有测试;自 JUnit 5.3 起可改为并行执行。文档同时提醒:不加同步就从多个线程使用同一个 Playwright 对象是不安全的,推荐每个线程创建并独占一个 Playwright 实例(来源)。使用@UsePlaywright时,文档给出的示例就是多个测试类各自标注@UsePlaywright(前文的TestExample即为一个,文档另配了一个含shouldReturnInnerHTMLshouldClickButton两个用例的Test2类)。

让“类内顺序、类间并行,最大线程数取 CPU 核心数的一半”,在 JUnit 配置中设置:

junit.jupiter.execution.parallel.enabled = true junit.jupiter.execution.parallel.mode.default = same_thread junit.jupiter.execution.parallel.mode.classes.default = concurrent junit.jupiter.execution.parallel.config.strategy=dynamic junit.jupiter.execution.parallel.config.dynamic.factor=0.5

如果不用@UsePlaywright而是手动管理生命周期,Test Runners 文档 的并行方案是:基类加@TestInstance(TestInstance.Lifecycle.PER_CLASS),把PlaywrightBrowser存为实例字段并在@BeforeAll/@AfterAll中创建/关闭,每个测试类继承该基类,从而“每个类实例拥有自己的 Playwright 副本”。

限制与注意事项

  • 该集成目前是实验功能(文档标题即 “JUnit (experimental)”),API 可能在后续版本调整,跟进 Release notes 中的相关说明。
  • 文档示例中的外部站点(wikipedia.orgplaywright.devgithub.com)需要网络可达,离线环境下请改用data:text/htmlpage.setContent(...)类的本地用例(文档示例已包含这类离线写法)。
  • %%VERSION%%是文档模板占位符而非真实版本号,写入pom.xml/build.gradle前必须替换,否则构建会直接失败。
  • 升级 Playwright 版本后,浏览器二进制可能需要同步重装,按 Browsers 文档 的说法每次更新 Playwright 后“可能需要重新运行install命令”。

进一步阅读:手动生命周期写法(@BeforeAll/@AfterAll方案)见 Running and debugging tests,测试运行器与 TestNG 对照见 Test Runners。

【免费下载链接】playwrightPlaywright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.项目地址: https://gitcode.com/GitHub_Trending/pl/playwright

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

MetaEditor命令行批量编译MT4/MT5 EA:从手工到自动化实战

做EA开发和量化交易的人&#xff0c;应该都有过这种体验&#xff1a;项目文件夹里有几十个.mq4或.mq5文件&#xff0c;改完一个公共的.mqh头文件&#xff0c;然后打开MetaEditor&#xff0c;一个个手动编译&#xff1b;编译完还得挨个确认左下角是不是真的出现了“0 errors, 0 …

作者头像 李华
网站建设 2026/9/9 19:16:05

凌晨三点的测试现场:从自动化到硬件测试的实战经验

凌晨三点&#xff0c;测试机房里的灯管发出细小的电流声&#xff0c;旁边自动测试架上的手机屏幕亮着微光&#xff0c;一台三卡GPU服务器风扇全速在转&#xff0c;屏幕上是一个跑到第47轮的回归用例。这个画面我太熟悉了。作为测试工程师&#xff0c;从移动端App到车载电子&…

作者头像 李华
网站建设 2026/9/9 19:14:17

基于CODESYS的汇川中大型PLC开发实战:环境搭建、ST编程与通讯故障排查

在工业自动化这行摸爬滚打多年&#xff0c;从日系PLC到国产PLC都碰过&#xff0c;但真正让我觉得“编程体验”上了一个台阶的&#xff0c;是第一次用CODESYS开发汇川AC801运动控制项目。汇川不只是做变频器和小型PLC&#xff0c;它的中大型PLC产品线——AC801实时运动控制器、A…

作者头像 李华
网站建设 2026/9/9 19:14:03

NDIS小端口驱动开发实战:从初始化到数据收发全解析

简介&#xff1a;这是面向瑞昱&#xff08;Realtek&#xff09;8111、8168、8169、8110等常见PCI千兆以太网控制器编写的NDIS 6.0小端口驱动示例源码&#xff0c;适合需要开发Windows网络驱动却缺少完整参考实例的工程师学习。压缩包采用RAR格式&#xff0c;共69个文件&#xf…

作者头像 李华
网站建设 2026/9/9 19:13:20

STM32驱动ADS1118:SPI接口实现多路ADC与热电偶测温完整教程

简介&#xff1a;基于STM32F103与STM32F407的ADS1118完整驱动方案&#xff0c;主要面向嵌入式开发者、电子竞赛学生以及从事高精度数据采集的工程师。程序覆盖4路单端、2路双差分和片内温度传感器三种采集模式&#xff0c;实现从寄存器初始化、SPI读写时序到多通道数据转换与错…

作者头像 李华
网站建设 2026/9/9 19:12:57

AutoGPT 后端因 JWT_JWKS_URL 为明文 HTTP 拒绝启动怎么解决?

AutoGPT 后端因 JWT_JWKS_URL 为明文 HTTP 拒绝启动怎么解决&#xff1f; 【免费下载链接】AutoGPT AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters. 项目地址…

作者头像 李华