在上一篇文章中,我们了解了 JavaScriptExecutor 的基本概念和原理。今天,让我们撸起袖子,通过两个完整的实战案例来深入体验这个强大工具的魅力。
实战演练:登录页面自动化
让我们通过一个接地气的例子来看看 JavaScriptExecutor 的威力。我们要在 LambdaTest 电子商务演练网站上实现以下测试场景:
- 导航到账户登录页面
- 输入登录凭据,并通过红色边框高亮显示字段(就像是给重要内容划重点)
- 点击登录按钮
- 打印页面标题和域名
- 验证登录成功
环境准备
首先,我们需要搭建测试舞台:
- 使用 IntelliJ IDE 创建 Maven 项目
- 在 pom.xml 中添加最新的 Selenium WebDriver 依赖
- 添加 TestNG 依赖
代码实现
创建测试类的骨架:
public class TestJavaScriptExecutor {
// 在类级别声明 WebDriver,因为需要在多个方法中使用
private WebDriver driver;
@BeforeTest
public void setup() {
// 启动 Chrome 浏览器,就像是打开工具箱
driver = new ChromeDriver();
driver.manage().window().maximize();
// 设置 30 秒隐式等待,让页面内容充分加载
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
}
@AfterTest
public void tearDown() {
// 优雅地关闭浏览器,就像是收拾工具箱
driver.quit();
}
}
核心测试方法实现:
@Test
public void testJavaScriptExecutorCommand() {
// 导航到登录页面
driver.get("https://***/index.php?route=account/login");
// 创建 JavaScriptExecutor 实例,就像是拿起魔法棒
JavascriptExecutor js = (JavascriptExecutor) driver;
// 处理邮箱字段:定位 -> 高亮 -> 输入 -> 恢复
WebElement emailAddressField = driver.findElement(By.id("input-email"));
js.executeScript("arguments[0].style.border='3px solid red'", emailAddressField);
emailAddressField.sendKeys("FunTester@demo.com");
js.executeScript("arguments[0].style.border='2px solid #ced4da'", emailAddressField);
// 处理密码字段:同样的套路
WebElement passwordField = driver.findElement(By.id("input-password"));
js.executeScript("arguments[0].style.border='3px solid red'", passwordField);
passwordField.sendKeys("FunTester123");
js.executeScript("arguments[0].style.border='2px solid #ced4da'", passwordField);
// 处理登录按钮:高亮并点击
WebElement loginBtn = driver.findElement(By.cssSelector("input.btn"));
js.executeScript("arguments[0].style.border='3px solid red'", loginBtn);
js.executeScript("arguments[0].click();", loginBtn);
// 获取页面信息,就像是收集战利品
String titleText = js.executeScript("return document.title;").toString();
System.out.println("Page Title is: " + titleText);
String domainName = js.executeScript("return document.domain;").toString();
System.out.println("Domain is: " + domainName);
// 验证登录成功
String myAccountHeader = driver.findElement(By.cssSelector("#content h2")).getText();
assertEquals(myAccountHeader, "My Account");
}
代码解析
这段代码的精妙之处在于:
1. 视觉反馈机制
使用红色边框高亮字段,让测试执行过程一目了然。这不仅有助于调试,还能让观看测试执行的人清楚地看到当前操作的元素:
js.executeScript("arguments[0].style.border='3px solid red'", emailAddressField);
2. JavaScript 点击的优势
通过 JavaScript 直接点击按钮,避免了可能的点击失效问题。相比传统的 element.click(),JavaScript 点击更加稳定可靠:
js.executeScript("arguments[0].click();", loginBtn);
3. 页面信息获取
直接获取页面的 title 和 domain,比传统方法更直接高效:
String titleText = js.executeScript("return document.title;").toString();
String domainName = js.executeScript("return document.domain;").toString();
异步操作实战:页面滚动
让我们再来看一个使用 executeAsyncScript() 的例子,实现以下测试场景:
- 导航到 LambdaTest 电子商务演练网站主页
- 滚动到页面底部
- 验证页面底部显示 FROM THE BLOG 文本
@Test
public void testExecuteAsyncScript() {
driver.get("https://ecommerce-playground.lambdatest.io");
JavascriptExecutor js = (JavascriptExecutor) driver;
// 异步滚动到页面底部,就像是坐电梯到顶楼
js.executeAsyncScript("var callback = arguments[arguments.length - 1];" +
"window.scrollBy(0,document.body.scrollHeight);" +
"callback();");
// 验证滚动结果
String fromTheBlogText = driver.findElement(By.cssSelector("#entry_217991 > h3")).getText();
assertEquals(fromTheBlogText, "FROM THE BLOG");
}
异步操作详解
这里的关键是 callback() 函数,它就像是信号灯,告诉系统异步操作已经完成。在 executeAsyncScript() 方法中,执行的脚本必须通过显式调用提供的 callback() 方法来发出完成信号。
异步脚本的结构
var callback = arguments[arguments.length - 1]; // 获取回调函数
// 执行异步操作
window.scrollBy(0,document.body.scrollHeight);
callback(); // 通知操作完成
为什么使用异步方法
- 更好的控制:可以精确控制操作的完成时机
- 避免竞态条件:确保操作完全完成后再继续执行
- 适合复杂场景:特别适合需要等待的操作,如动画、AJAX 请求等
实战技巧总结
1. 元素高亮技巧
在测试执行过程中高亮元素,不仅有助于调试,还能提升测试的可视化效果:
// 高亮元素
js.executeScript("arguments[0].style.border='3px solid red'", element);
// 恢复原样
js.executeScript("arguments[0].style.border='2px solid #ced4da'", element);
2. 强制点击技巧
当元素被遮挡或不在视口中时,JavaScript 点击比常规点击更可靠:
js.executeScript("arguments[0].click();", element);
3. 页面信息获取技巧
直接通过 JavaScript 获取页面信息,比 WebDriver API 更直接高效:
String title = js.executeScript("return document.title;").toString();
String url = js.executeScript("return document.URL;").toString();
String domain = js.executeScript("return document.domain;").toString();
4. 滚动操作技巧
JavaScript 提供了更灵活的滚动控制:
// 滚动到元素位置
js.executeScript("arguments[0].scrollIntoView(true);", element);
// 滚动指定距离
js.executeScript("window.scrollBy(0, 500);");
// 滚动到页面底部
js.executeScript("window.scrollBy(0, document.body.scrollHeight);");
常见问题与解决方案
问题 1:元素点击失效
现象:使用 element.click() 无法点击元素
解决方案:使用 JavaScript 强制点击
js.executeScript("arguments[0].click();", element);
问题 2:页面滚动不到位
现象:元素不在视口中,无法操作
解决方案:先滚动到元素位置
js.executeScript("arguments[0].scrollIntoView(true);", element);
问题 3:异步操作时机不准确
现象:操作执行过早或过晚
解决方案:使用 executeAsyncScript() 精确控制时机
js.executeAsyncScript("var callback = arguments[arguments.length - 1]; /* 异步操作 */ callback();");
总结
通过这两个实战案例,我们深入体验了 JavaScriptExecutor 在实际项目中的应用。从同步操作到异步操作,从元素交互到页面信息获取,JavaScriptExecutor 展现了其强大的能力和灵活性。