1. 项目概述:为什么是 Playwright for Java?

如果你是一名 Java 后端开发,或者正在从 Selenium 转向更现代的自动化测试方案,那么 Playwright 这个名字你肯定不陌生。但很多人第一反应是:这不是 Node.js 那边的工具吗?没错,Playwright 最初确实是为 Node.js 生态量身打造的,但微软团队很快意识到,要让这个强大的工具真正普及,必须拥抱企业级开发中最主流的语言之一——Java。于是,Playwright for Java 应运而生,它不是一个简单的语言绑定,而是一个深度集成、充分利用 Java 并发特性和强类型优势的 SDK。

我最初接触 Playwright 也是因为一个老项目的自动化测试重构。当时团队还在用 Selenium WebDriver 配合 TestNG,一套用例跑下来动辄半小时,浏览器兼容性问题和脆弱的元素定位让人头疼不已。直到尝试了 Playwright,我才发现自动化测试可以如此“清爽”:无需手动管理各种浏览器驱动,内置的自动等待机制大幅减少了 Flaky Tests(不稳定的测试),对现代单页应用(SPA)的支持近乎完美。更重要的是,它的 Java API 设计得非常“Java”,让你感觉就像在使用一个原生的 Java 库,而不是一个外来移植品。这篇文章,我就带你从零开始,拆解 Playwright for Java 的核心概念,并通过实际案例,让你能快速上手,应用到你的项目中,无论是做 UI 自动化测试、爬虫,还是日常的重复性网页操作。

2. 核心概念与架构解析

2.1 Playwright 的“三位一体”模型

理解 Playwright,首先要抛开 Selenium 那种“一个驱动对应一个浏览器”的线性思维。Playwright 采用了一个更清晰的三层架构: Playwright -> Browser -> Context -> Page 。这听起来有点抽象,我用一个公司的组织架构来类比:

  • Playwright 对象 :就像公司的“创始人”或“工厂”。你的所有自动化旅程都从这里开始。它的主要职责是启动和管理不同类型的浏览器“实例”(BrowserType)。在 Java 中,你通过 Playwright.create() 来创建这个入口点。
  • Browser 对象 :可以理解为一家“分公司”或一条“生产线”。它代表一个实际的浏览器进程,比如一个 Chrome 或 Firefox 的实例。你可以创建多个独立的 Browser 对象,它们彼此隔离。通过 playwright.chromium().launch() 这样的方式来启动。
  • BrowserContext 对象 :这是 Playwright 最精妙的设计之一,相当于分公司里的一个“独立项目组”。每个 Context 拥有独立的会话(Session)、Cookie、本地存储和缓存,但共享同一个浏览器进程的资源。这让你能轻松模拟多个用户同时登录、进行并行测试,而无需启动多个沉重的浏览器进程,资源消耗大大降低。
  • Page 对象 :这是最终与网页交互的“一线员工”。一个 Context 下可以创建多个 Page(即多个标签页)。你的绝大部分操作,如跳转网址、点击按钮、输入文本,都在 Page 对象上完成。

为什么要这么设计?核心优势在于 隔离性与效率的平衡 。在 Selenium 中,如果你想隔离两个测试场景,通常需要启动两个浏览器,开销巨大。而在 Playwright 中,你只需在一个浏览器进程下创建两个 Context,就能实现完美的隔离,速度更快,资源占用更少。

2.2 Java API 的设计哲学:同步与异步

Playwright 原生是异步的(基于 Node.js 的 Promise),但它的 Java API 提供了两种风格: 同步 API 异步 API 。对于大多数从 Selenium 转过来或有传统 Java 背景的开发者,同步 API 更易上手,代码写起来是顺序执行的,更符合直觉。

// 同步 API 示例(最常用)
try (Playwright playwright = Playwright.create()) {
    Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
    BrowserContext context = browser.newContext();
    Page page = context.newPage();
    page.navigate("https://example.com");
    System.out.println(page.title()); // 同步等待并获取标题
}

而异步 API(基于 CompletableFuture )则提供了更高的灵活性,适合在复杂的并发场景下榨干性能。不过,对于入门和 90% 的用例,同步 API 完全够用且更不易出错。Playwright 的同步 API 底层其实封装了异步操作,并帮你处理好了等待,这也是它比 Selenium 更稳定的原因之一——它内置了智能等待,而不是简单粗暴的 Thread.sleep

2.3 与 Selenium 的关键差异点

很多人在选择时会纠结。这里我列几个最关键的差异,帮你决策:

特性维度 Playwright (Java) Selenium WebDriver
架构 通过 DevTools Protocol 等现代化协议直接与浏览器通信 通过标准化的 W3C WebDriver 协议通信
启动速度 快。浏览器和驱动由 Playwright 统一管理,自动下载。 较慢。需要手动匹配和下载浏览器驱动。
自动等待 内置且强大 。几乎所有操作(如 click , fill )都自动等待元素可操作。 需要手动设置隐式/显式等待,否则极易因元素未加载而失败。
浏览器支持 统一支持 Chromium, Firefox, WebKit。API 一致,无需为不同浏览器写适配代码。 支持更广泛的浏览器,但不同浏览器可能需要特定配置,行为偶有差异。
网络拦截与 Mock 原生支持,非常方便。可以轻松拦截修改请求、模拟 API 响应。 需要借助其他库(如 BrowserMob Proxy),配置复杂。
移动端模拟 通过设备描述符精准模拟手机视口、User-Agent 等,体验真实。 支持,但配置相对基础。
录制工具 内置 playwright codegen ,可生成 Java 代码,是学习利器。 有 Selenium IDE,但功能相对简单。
社区与生态 增长迅速,由微软维护,但 Java 生态的第三方库(如报告工具集成)目前略少于 Selenium。 极其成熟,有海量的社区解决方案、集成和文档。

我的选择建议 :如果你的项目是全新的,或者正被 Selenium 的稳定性问题困扰,强烈建议尝试 Playwright。它的“开箱即用”体验和稳定性提升是立竿见影的。如果项目严重依赖 Selenium 的庞大生态(如某些特定的云测试平台插件),或者需要支持 IE 等老旧浏览器,那么 Selenium 仍是唯一选择。

3. 环境搭建与项目初始化

3.1 依赖管理与构建工具配置

Playwright for Java 主要通过 Maven 或 Gradle 进行依赖管理。这里以最常用的 Maven 为例。

首先,在你的 pom.xml 中添加 Playwright 依赖。 强烈建议使用最新稳定版本 ,你可以去 Maven Central 查看。

<dependency>
    <groupId>com.microsoft.playwright</groupId>
    <artifactId>playwright</artifactId>
    <version>1.44.0</version> <!-- 请替换为最新版本 -->
</dependency>

添加依赖后,当你第一次运行任何使用 Playwright 的代码时,它会自动下载所需的浏览器二进制文件(Chromium, Firefox, WebKit)到本地缓存中。这个过程是自动的,但有时可能因为网络问题失败。

3.2 解决首次运行的“浏览器下载”问题

自动下载虽然方便,但在公司内网或网络不稳定环境下可能出问题。这时,你可以选择手动安装。

方法一:使用 Maven Goal(推荐) Playwright 提供了一个 Maven 插件,可以显式执行浏览器安装。

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

或者,如果你已经写了一个简单的测试类,直接运行它也会触发下载。

方法二:使用 Playwright CLI 如果你全局安装了 Playwright CLI,也可以直接使用。但 Java 版更推荐用 Maven Goal。

方法三:完全离线部署 在能联网的机器上,先让 Playwright 完成下载。浏览器通常存放在 ~/.cache/ms-playwright (Linux/Mac)或 %USERPROFILE%\AppData\Local\ms-playwright (Windows)目录下。你可以将这个目录打包,复制到目标机器对应的位置。然后,在启动代码中指定浏览器可执行文件路径:

BrowserType.LaunchOptions options = new BrowserType.LaunchOptions()
        .setExecutablePath(Paths.get("/your/offline/path/chrome-win/chrome.exe")); // 指定路径
Browser browser = playwright.chromium().launch(options);

3.3 编写你的第一个脚本:验证环境

创建一个简单的 Java 类来验证一切是否就绪。

import com.microsoft.playwright.*;

public class FirstScript {
    public static void main(String[] args) {
        // 1. 创建 Playwright 实例。try-with-resources 确保最后关闭。
        try (Playwright playwright = Playwright.create()) {
            // 2. 启动 Chromium 浏览器。setHeadless(false) 表示显示浏览器界面,方便调试。
            Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
            // 3. 创建一个新的浏览器上下文(Context)
            BrowserContext context = browser.newContext();
            // 4. 在上下文中打开一个新页面(Page)
            Page page = context.newPage();
            // 5. 导航到目标网址
            page.navigate("https://playwright.dev/java/");
            // 6. 获取页面标题并打印
            System.out.println("页面标题: " + page.title());
            // 7. 为了看清效果,等待几秒(实际脚本中应使用 Playwright 的等待机制,而非 sleep)
            page.waitForTimeout(3000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // try-with-resources 会自动调用 playwright.close(),关闭所有浏览器。
    }
}

运行这个程序,你应该能看到一个浏览器窗口打开,访问 Playwright 官网,然后在控制台打印出标题,最后浏览器自动关闭。恭喜,你的 Playwright Java 环境已经成功搭建!

实操心得 :在开发调试阶段,建议将 setHeadless(false) 设为 false ,这样你能直观地看到浏览器的操作过程,便于定位问题。在 CI/CD 流水线或生产环境运行时,再改为 true (无头模式),这样不需要图形界面,运行更高效。

4. 核心 API 与元素交互实战

4.1 元素定位器(Locators):稳定定位的基石

元素定位是自动化脚本的“地基”。Playwright 的定位器 API 设计得非常强大和灵活。核心方法是 page.locator(selector)

常用定位策略:

  • CSS 选择器 :最通用、最推荐的方式。 page.locator("button.submit")
  • 文本定位 :通过元素文本内容定位,对动态变化的 CSS 类不敏感。 page.locator("text=登录")
  • XPath :功能强大但可能较慢且脆弱,慎用。 page.locator("//button[@id='submit']")
  • React/Vue 组件定位 :Playwright 独家支持,如果你测试的是基于这些框架的应用,定位会非常精准。 page.locator("_react=SubmitButton[enabled=true]")

组合定位与过滤: Playwright 定位器支持链式调用,非常符合 Java 流的操作风格。

// 找到第一个 div 下的所有 li,然后过滤出包含“项目”文本的第二个
Locator item = page.locator("div.list-container > li")
                  .filter(new Locator.FilterOptions().setHasText("项目"))
                  .nth(1); // 索引从0开始

// 通过另一个元素来定位(比如在某个特定的表单里找输入框)
Locator form = page.locator("form#login-form");
Locator usernameInput = form.locator("input[name='username']");

避坑指南 :尽量避免使用基于索引的定位(如 :nth-child(3) ),因为页面结构一变就失效。优先使用具有唯一性的 ID、属性,或者结合文本内容定位。Playwright 的 text= 定位器非常智能,它会进行子字符串匹配,且对空格换行不敏感,比 Selenium 的 By.linkText 好用得多。

4.2 基本交互操作:点击、输入与等待

定位到元素后,就可以进行交互了。Playwright 的所有交互操作都 内置了自动等待

// 点击操作
page.locator("button#submit").click(); // 等待按钮可点击后再点击

// 输入文本
page.locator("input#username").fill("myUsername"); // fill() 会先清空再输入
page.locator("input#username").type("myUsername"); // type() 是模拟键盘逐个输入
// 对于富文本编辑器等特殊场景,可能需要先点击再输入
page.locator("div[contenteditable=true]").click();
page.keyboard().type("Hello World");

// 处理下拉框(Select)
Locator countrySelect = page.locator("select#country");
countrySelect.selectOption("china"); // 通过 value 或 label 选择
countrySelect.selectOption(new SelectOption().setLabel("中国")); // 通过标签选择

// 上传文件(极其简单!)
page.locator("input[type='file']").setInputFiles(Paths.get("/path/to/file.pdf"));
// 上传多个文件
page.locator("input[type='file']").setInputFiles(new Path[] {Paths.get("file1.pdf"), Paths.get("file2.pdf")});

等待策略: 除了操作自带的等待,你还可以显式等待。

  • page.waitForSelector(“selector”) : 等待某个元素出现在 DOM 中。
  • page.waitForURL(“**url”) : 等待导航到特定 URL。
  • locator.waitFor() : 等待该定位器对应的元素满足某种状态(如可见、隐藏)。
// 等待加载动画消失
page.locator("div.loading-spinner").waitFor(new Locator.WaitForOptions().setState(WaitForSelectorState.HIDDEN));
// 等待某个元素出现并包含特定文本
page.locator("h1.success").waitFor(new Locator.WaitForOptions().setHasText(“操作成功”));

4.3 处理弹窗、框架与多标签页

对话框(Alert, Confirm, Prompt): Playwright 通过监听事件来处理对话框,无需像 Selenium 那样先切换再操作。

// 监听对话框事件,并在触发时接受(相当于点击“确定”)
page.onDialog(dialog -> {
    System.out.println("对话框信息: " + dialog.message());
    dialog.accept(); // 接受。dialog.dismiss() 是取消。
});
// 然后执行会触发对话框的操作,例如点击删除按钮
page.locator("button.delete").click();

Frame 和 iframe: 处理 iframe 的关键是先获取到 Frame 对象。

// 通过名称或 URL 定位 Frame
Frame frame = page.frame(“frame-name”);
// 或者通过选择器定位 iframe 元素,再获取其 contentFrame
Frame frame = page.locator(“iframe#myIframe”).contentFrame();
// 然后在 Frame 对象上进行操作,就像操作 Page 一样
frame.locator(“button.inside-frame”).click();

多标签页(Tabs):

// 点击一个会打开新标签页的链接(监听 popup 事件)
Page newPage = page.waitForPopup(() -> { // waitForPopup 返回新页面的 Page 对象
    page.locator(“a[target=’_blank’]”).click();
});
// 现在可以操作新页面了
newPage.bringToFront(); // 切换到该标签页
System.out.println(newPage.title());

5. 高级特性与实战技巧

5.1 网络拦截与 Mock:提升测试稳定性与速度

这是 Playwright 的王牌功能之一。你可以拦截和修改任何网络请求,这对于测试以下场景至关重要:

  1. 屏蔽第三方资源 (如广告、分析脚本),加速测试。
  2. Mock API 响应 ,在后台服务不可用或未完成时,前端功能依然可测。
  3. 验证请求是否按预期发送
// 监听所有请求和响应
page.onRequest(request -> System.out.println(“>> “ + request.method() + “ “ + request.url()));
page.onResponse(response -> System.out.println(“<< “ + response.status() + “ “ + response.url()));

// 拦截并修改请求(例如,在所有请求头中添加一个令牌)
page.route(“**/*”, route -> {
    Map<String, String> headers = new HashMap<>(route.request().headers());
    headers.put(“X-Custom-Token”, “my-secret-token”);
    route.resume(new Route.ResumeOptions().setHeaders(headers));
});

// 拦截特定请求并返回 Mock 数据(关键!)
page.route(“**/api/user/profile”, route -> {
    // 构造一个模拟的 JSON 响应
    Map<String, Object> mockData = Map.of(
        “username”, “mockUser”,
        “email”, “mock@example.com”
    );
    route.fulfill(new Route.FulfillOptions()
        .setStatus(200)
        .setContentType(“application/json”)
        .setBody(playwright.gson().toJson(mockData))); // 使用 Playwright 内置的 Gson
});

// 中止对某些资源的请求(如图片、样式表),加快速度
page.route(“**/*.{png,jpg,jpeg,svg,css}”, route -> route.abort());

5.2 设备模拟与移动端测试

Playwright 内置了众多主流移动设备(如 iPhone, Pixel, Galaxy)的描述符,可以一键模拟。

// 使用预定义的设备描述符
BrowserContext iphoneContext = browser.newContext(playwright.devices().get(“iPhone 13 Pro”));
Page mobilePage = iphoneContext.newPage();
mobilePage.navigate(“https://m.example.com”);
// 此时 mobilePage 的视口、User-Agent、触摸事件等都模拟了 iPhone 13 Pro

// 自定义设备参数
BrowserContext customContext = browser.newContext(new Browser.NewContextOptions()
        .setViewportSize(375, 812) // 视口大小
        .setDeviceScaleFactor(3) // 设备像素比
        .setIsMobile(true)
        .setHasTouch(true)
        .setUserAgent(“Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) …”));

5.3 录制与代码生成:快速创建脚本骨架

对于初学者或快速探索新页面, playwright codegen 是神器。虽然它是一个命令行工具,但生成的是 Java 代码。

  1. 打开终端,运行:
    mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args=“codegen https://example.com”
    
  2. 会自动打开两个窗口:一个浏览器,一个代码生成器。
  3. 在浏览器中操作,右侧的代码生成器会实时生成对应的 Java 代码。
  4. 操作完成后,你可以将生成的代码复制到你的 IDE 中,作为脚本的起点。

注意事项 :生成的代码通常比较“直白”,可能包含大量基于索引的定位。你需要手动优化这些定位器,使其更具可读性和鲁棒性(例如,将 locator(‘:nth-child(3)’) 改为更具语义的定位)。

5.4 集成测试框架与生成报告

单纯的脚本还不够,我们需要将其集成到测试框架中,并生成漂亮的报告。这里以 JUnit 5 Allure 为例。

1. 集成 JUnit 5: 添加 JUnit 依赖,并利用 @BeforeEach , @AfterEach 管理 Playwright 生命周期。

import com.microsoft.playwright.*;
import org.junit.jupiter.api.*;

import static org.junit.jupiter.api.Assertions.*;

public class LoginTest {
    // 共享的静态变量
    static Playwright playwright;
    static Browser browser;
    // 每个测试独立的变量
    BrowserContext context;
    Page page;

    @BeforeAll
    static void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(true)); // CI 环境用无头
    }

    @AfterAll
    static void closeBrowser() {
        browser.close();
        playwright.close();
    }

    @BeforeEach
    void createContextAndPage() {
        context = browser.newContext();
        // 可以在这里设置全局的 Viewport、User-Agent 等
        page = context.newPage();
    }

    @AfterEach
    void closeContext() {
        context.close();
    }

    @Test
    void shouldLoginSuccessfully() {
        page.navigate(“https://your-app.com/login”);
        page.locator(“input#username”).fill(“testuser”);
        page.locator(“input#password”).fill(“password123”);
        page.locator(“button[type=’submit’]”).click();
        // 使用 Playwright 的断言,它自带等待
        assertTrue(page.locator(“text=欢迎回来,testuser”).isVisible());
    }
}

2. 生成 Allure 报告并附加失败截图/视频: Playwright 支持在测试失败时自动截图和录制视频,这结合 Allure 非常强大。

首先,在创建 BrowserContext 时配置录像选项:

@BeforeEach
void createContextAndPage() {
    // 为每个测试 Context 设置录像,保存到 videos 目录
    context = browser.newContext(new Browser.NewContextOptions()
            .setRecordVideoDir(Paths.get(“target/videos/”))); // Maven 项目通常输出到 target
    page = context.newPage();
}

@AfterEach
void closeContext(TestInfo testInfo) {
    // 测试结束后,保存视频并附加到 Allure 报告
    if (context != null) {
        // 获取该 Context 录制的视频路径
        Path videoPath = context.video().path();
        context.close();
        // 仅当测试失败且视频文件存在时,附加到报告
        if (testInfo.getStatus() == TestStatus.FAILED && videoPath.toFile().exists()) {
            Allure.addAttachment(“测试执行视频”, “video/webm”, Files.newInputStream(videoPath), “.webm”);
        }
    }
}

同时,在 @AfterEach 中也可以添加失败截图:

if (testInfo.getStatus() == TestStatus.FAILED) {
    // 截图并附加到 Allure
    byte[] screenshot = page.screenshot(new Page.ScreenshotOptions().setFullPage(true));
    Allure.addAttachment(“失败截图”, “image/png”, new ByteArrayInputStream(screenshot), “.png”);
}

最后,配置你的 Maven pom.xml 或 Gradle 以使用 Allure 插件运行测试并生成报告。

6. 常见问题排查与性能优化

6.1 典型错误与解决方案速查表

问题现象 可能原因 解决方案
TimeoutError: Timeout 30000ms exceeded. 1. 元素定位器找不到或永远不满足可见/可点击状态。
2. 页面加载太慢或网络请求阻塞。
1. 检查定位器是否正确,使用 page.pause() 或浏览器开发者工具复核。
2. 增加超时时间: locator.click(new Locator.ClickOptions().setTimeout(60000))
3. 检查是否有未处理的模态框遮挡。
Error: Target closed 页面或浏览器在你尝试操作时已被关闭。 检查代码逻辑,确保在操作 Page 对象时,其所属的 Context 和 Browser 未被提前关闭。常见于异步操作未正确同步。
Element is not attached to the DOM 你定位到的元素在操作前已被从页面移除(动态 DOM)。 1. 使用更稳定的定位器,避免定位到动态生成的容器内部元素。
2. 使用 locator.waitFor() 确保元素稳定存在再操作。
3. 考虑使用 page.waitForFunction() 等待某个 JavaScript 条件成立。
脚本在 CI 服务器上失败,本地却成功 1. CI 环境是无头模式,可能与有头模式行为有细微差异。
2. CI 环境资源(CPU/内存)不足。
3. 网络或代理设置不同。
1. 本地也使用 setHeadless(true) 运行测试,复现问题。
2. 为 Browser 启动增加参数: .setArgs(Arrays.asList(“--disable-dev-shm-usage”, “--no-sandbox”)) 解决 Docker 中常见问题。
3. 在 CI 脚本中明确设置 HTTP 代理或无代理。
文件上传不工作 文件选择输入框可能是动态生成或隐藏在复杂组件中。 1. 确保 setInputFiles 调用在输入框可见可交互之后。
2. 对于隐藏的输入框,可能需要先用 JavaScript 使其可见: page.evalOnSelector(“input[type=’file’]”, “el => el.style.display = ‘block’”)
3. 考虑使用 Page.setInputFiles 方法。
页面卡在加载状态 页面有未完成的 long-polling 请求或 WebSocket 连接。 使用 page.waitForLoadState(LoadState.NETWORKIDLE) 等待网络空闲,或使用 page.waitForTimeout() 作为最后手段,但尽量避免。

6.2 性能优化与最佳实践

  1. 复用 Browser 和 Context :创建 Browser 实例开销最大。在测试套件级别( @BeforeAll )创建并共享一个 Browser 实例,在每个测试用例( @BeforeEach )中创建独立的 Context。这是平衡隔离性和性能的最佳实践。
  2. 善用无头模式 :在 CI/CD 环境中务必使用 setHeadless(true) 。如果需要调试,可以通过环境变量控制,或者使用 setHeadless(false).setSlowMo(500) slowMo 可以减慢操作速度,方便观察)。
  3. 拦截不必要的资源 :使用 page.route 拦截并中止对图片、字体、样式表等静态资源的请求,可以显著提升测试执行速度。
  4. 并行执行 :Playwright 天生支持并行。在 JUnit 中,可以通过 @Execution(ExecutionMode.CONCURRENT) 注解(需配合 junit-platform.properties 配置)实现测试类或方法级别的并行。确保每个测试线程使用自己独立的 Context。
  5. 选择正确的等待 :优先使用 Playwright 内置的自动等待和 locator.waitFor() ,避免硬编码 Thread.sleep 。对于复杂的自定义等待条件,使用 page.waitForFunction()
  6. 定期清理 :确保在 @AfterEach @AfterAll 中正确关闭 Context 和 Browser,防止资源泄漏导致内存不足。

6.3 调试技巧

  • page.pause() :在代码中插入这行,运行时会自动打开 Playwright Inspector,你可以单步执行、查看当前 DOM 快照、实时生成定位器,是最强的调试工具。
  • 录制追踪(Tracing) :在测试开始时启动追踪,结束时停止并保存。它记录了测试期间的所有操作、网络请求、控制台日志,生成一个可视化的 ZIP 文件,可以用浏览器打开复盘。
    @BeforeEach
    void startTracing() {
        context.tracing().start(new Tracing.StartOptions().setScreenshots(true).setSnapshots(true));
    }
    @AfterEach
    void stopTracing(TestInfo testInfo) {
        context.tracing().stop(new Tracing.StopOptions()
                .setPath(Paths.get(“target/traces/” + testInfo.getDisplayName() + “.zip”)));
    }
    
  • 查看控制台日志 page.onConsoleMessage(msg -> System.out.println(“CONSOLE: “ + msg.text()));

从概念理解到环境搭建,从基础操作到高级应用,再到集成调试,Playwright for Java 提供了一套完整、现代且高效的浏览器自动化解决方案。它降低了过去在 Selenium 中常见的配置和维护成本,将开发者的精力更多地聚焦在测试逻辑和业务验证本身。开始尝试将它引入你的下一个项目吧,你会发现编写和维护自动化脚本,不再是一件令人望而生畏的苦差事。

更多推荐