《刚刚问世》系列初窥篇-Java+Playwright自动化测试-- 操作单选和多选按钮 - 下篇(详细教程)

《刚刚问世》系列初窥篇-Java+Playwright自动化测试-- 操作单选和多选按钮 - 下篇(详细教程)

《刚刚问世》系列初窥篇-Java+Playwright自动化测试-- 操作单选和多选按钮 - 下篇(详细教程)

前言在上一篇文章中,我们初步了解了如何使用 Java + Playwright 进行单选和多选按钮的基本操作。今天,我们将深入探讨更复杂的场景:动态加载的单选按钮联动选择多选按钮的全选/反选,以及如何处理非原生(自定义)样式的按钮。这些技巧在实际项目中非常实用,能帮你应对大部分前端交互挑战。## 准备工作:环境与依赖确保你的项目中已经导入 Playwright 的 Java 依赖(Maven示例):xml<dependency> <groupId>com.microsoft.playwright</groupId> <artifactId>playwright</artifactId> <version>1.40.0</version></dependency>同时,建议使用最新版本的浏览器驱动,Playwright 会自动管理。## 技巧一:操作动态加载的单选按钮很多现代应用(如 React、Vue)的单选按钮是在用户交互后才渲染的。例如一个“选择支付方式”的弹窗,需要点击触发后才出现。### 场景模拟假设有一个【立即支付】按钮,点击后出现一组选项:微信支付、支付宝、银行卡。### 核心代码示例(Java)javaimport com.microsoft.playwright.*;import org.junit.jupiter.api.*;public class DynamicRadioTest { static Playwright playwright; static Browser browser; static Page page; @BeforeAll static void setup() { playwright = Playwright.create(); browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false)); page = browser.newPage(); page.navigate("https://example.com/payment"); // 假设的测试页面 } @Test void testDynamicRadio() { // 1. 点击触发按钮,让单选按钮组出现 page.click("button#showPaymentOptions"); // 2. 等待单选按钮渲染完成(使用定位器等待) page.waitForSelector("input[name='payment'][type='radio']", new Page.WaitForSelectorOptions() .setTimeout(5000)); // 最多等5秒 // 3. 选择第二个选项(支付宝) // 使用 nth() 定位第二个 radio page.locator("input[name='payment'][type='radio']").nth(1).check(); // 4. 断言:验证支付宝被选中 boolean isAlipayChecked = page.locator("input[value='alipay']").isChecked(); Assertions.assertTrue(isAlipayChecked, "支付宝应该被选中"); System.out.println("✅ 动态单选按钮操作成功"); } @AfterAll static void tearDown() { browser.close(); playwright.close(); }}注释解析:-waitForSelector确保动态元素加载完成。-nth(1)选取第二个 radio(索引从0开始)。-isChecked()验证是否被选中,返回布尔值。## 技巧二:联动单选与多选在实际业务中,经常遇到“如果选了某个选项,就禁用其他选项”的逻辑。例如:选择“学生”身份后,学历选项自动禁用“博士”。### 场景模拟一个表单包含身份选择(单选:学生/职工)和学历选择(多选:本科/硕士/博士)。当身份为“学生”时,学历中的“博士”不可选。### 代码示例java@Testvoid testCascadingSelection() { // 1. 选择身份为“学生” page.locator("label:has-text('学生')").click(); // 假设 radio 被 label 包裹 // 2. 等待联动效果生效(通常需要短暂延迟,或用 waitForFunction) page.waitForFunction("!document.querySelector('input[value=\"博士\"]').disabled"); // 3. 尝试验证“博士”是否被禁用 Locator phdCheckbox = page.locator("input[value='博士']"); boolean isDisabled = phdCheckbox.isDisabled(); Assertions.assertTrue(isDisabled, "博士选项应该被禁用"); // 4. 切换身份为“职工” page.locator("label:has-text('职工')").click(); // 5. 等待状态恢复 page.waitForFunction("!document.querySelector('input[value=\"博士\"]').disabled"); // 6. 现在博士应该可用,选中它 phdCheckbox.check(); Assertions.assertTrue(phdCheckbox.isChecked(), "博士应该被选中"); System.out.println("✅ 联动逻辑验证通过");}要点说明:-waitForFunction用于等待 JavaScript 条件满足,这里是等待disabled属性变化。- 使用label:has-text()选择器更贴近用户视角,也避免直接依赖idname。## 技巧三:多选按钮的全选、反选与批量操作很多列表页会提供“全选/反选”功能,例如购物车、权限管理。我们需要模拟用户点击全选、验证所有子项被选中,再取消全选。### 高效批量操作代码java@Testvoid testSelectAllAndDeselectAll() { // 假设页面有5个多选框,id 从 item1 到 item5,以及一个全选框 id="selectAll" // 1. 点击全选 page.check("#selectAll"); // 2. 验证所有子项都被选中 for (int i = 1; i <= 5; i++) { Locator item = page.locator("#item" + i); Assertions.assertTrue(item.isChecked(), "项目" + i + "应该被选中"); } // 3. 取消其中一个子项(模拟用户手动取消) page.uncheck("#item3"); // 4. 验证全选框状态变为未选中 boolean isAllChecked = page.locator("#selectAll").isChecked(); Assertions.assertFalse(isAllChecked, "取消子项后全选框应取消"); // 5. 重新选中所有子项 page.locator("input[type='checkbox']").check(); // 批量选中所有 checkbox // 6. 验证全选框又变回选中 isAllChecked = page.locator("#selectAll").isChecked(); Assertions.assertTrue(isAllChecked, "所有子项选中后全选框应选中"); System.out.println("✅ 全选/反选逻辑完美运行");}关键点:- 使用check()uncheck()方法直接操作,比click()更明确。- 批量操作时,page.locator("input[type='checkbox']").check()会选中页面上所有 checkbox(谨慎使用,建议加范围限制)。- 注意业务逻辑:全选通常需要监听子项的变化,Playwright 的isChecked()可以实时反映状态。## 技巧四:处理自定义样式的按钮有些项目使用 div、span 或第三方库(如 Material-UI)模拟单选/多选,这些元素不是原生<input>标签,无法直接使用check()方法。此时需要模拟点击,并验证 CSS 类的变化。### 实战代码java@Testvoid testCustomRadioButton() { // 假设页面使用 div 模拟单选按钮,选中时添加 class="selected" // <div class="radio-option">