Selenium是一个开源的工具和库套件,允许您与浏览器交互执行各种操作,如发送文本、点击按钮、选择下拉菜单等。
然而,在一些情况下,实际的Selenium WebDriver命令不像预期那样工作,因为Selenium无法直接与WebElements交互。这时候就需要用到JavaScriptExecutor。
在本博客中,我们将讨论Selenium中的JavaScriptExecutor,以及如何开始实际应用案例和示例。
JavaScriptExecutor在Selenium中是什么?
JavaScriptExecutor是Selenium提供的一个接口,帮助执行JavaScript命令。此接口提供了在选定窗口或当前网页上运行JavaScript的方法。它适用于Selenium支持的所有语言绑定。
在自动化测试脚本中,可以通过导入以下包直接使用Selenium中的JavaScriptExecutor:
org.openqa.selenium.JavascriptExecutor
Selenium中的JavaScriptExecutor提供了两种与WebElements交互的方法:
executeScript()
– 此方法在Selenium中当前选定的窗口或框架的上下文中执行JavaScript。脚本将作为匿名函数的主体执行。executeAsyncScript()
– 这个方法在Selenium中的当前选定窗口或框架的上下文中执行异步的JavaScript代码片段。该脚本将作为匿名函数的主体执行。
注意:使用executeAsyncScript()
方法调用的脚本必须使用callback()
函数来表示执行完成。
在需要在待测浏览器中执行休眠或在AJAX应用程序中同步测试时,通常会使用executeAsyncScript()
方法来调用方法。
为什么在Selenium中使用JavaScriptExecutor?
有些WebDriver命令由于多种原因无法按预期工作的场景,如下:
- Selenium无法直接与WebElements交互
- 执行动作,如滚动到视图中,单击位于覆盖层后面的WebElements,或在只读字段中设置值
- 执行特定于浏览器的行为,如动态修改DOM
在这些情况下,我们会借助Selenium中的JavaScriptExecutor。
传统上,我们使用Selenium定位器,如ID、名称、CSS选择器、XPath等,来定位一个WebElement。如果这些定位器不起作用,或者您正在处理一个棘手的XPath,在这种情况下,JavaScriptExecutor有助于定位所需的WebElement。
有些情况下,click()
方法可能无法在所有的Web浏览器上运行,或者Web控件在不同浏览器上的行为可能不同。为了克服这种情况,应该使用JavaScriptExecutor来执行点击操作。
众所周知,浏览器内部有JavaScript实现,并且能够理解JavaScript命令。因此,了解Selenium中的JavaScriptExecutor将使我们能够更有效地执行各种操作。
Selenium中JavaScriptExecutor的基础知识
本节的目的是提供关于在Selenium中实现JavaScriptExecutor的步骤的高层次概念。在演示中,我们将使用Java作为首选编程语言。
让我们看一下关键步骤。
1. 导入与JavaScriptExecutor相关的包:
import org.openqa.selenium.JavascriptExecutor;
2. 使用JavaScriptExecutor,创建一个接口的引用,并通过强制转换将其分配给WebDriver实例:
JavascriptExecutor js = (JavascriptExecutor) driver;
3. 调用executeAsyncScript()
或executeScript()
方法。例如,executeScript()
的语法如下:
js.executeScript(java.lang.String script, java.lang.Object... args)
演示:在Selenium中使用JavaScriptExecutor
在查看如何在Selenium中使用JavaScriptExecutor之前,请遵循以下先决条件:
- 使用IntelliJ IDE创建一个新的Maven项目
- 在pom.xml中添加最新的Selenium WebDriver依赖
- 在pom.xml中添加最新的TestNG依赖
我们将使用LambdaTest电子商务平台网站,在本地Chrome浏览器上运行测试来演示Selenium中JavaScriptExecutor的工作。
测试场景1
我们的目标是编写一个简单的代码,以示例的方式使用executeScript()
方法来完成以下测试场景。
- 导航至LambdaTest电子商务平台网站的账户登录页面。
- 输入有效的登录凭据,并通过突出显示具有红色边框的字段来单击登录按钮。
- 打印页面标题和域名。
- 断言成功登录时显示页面标题“我的账户”。
实现
为实现测试场景创建一个新的TestJavaScriptExecutor
类。我们首先在这个测试类中创建两个方法,这些方法将允许我们设置和优雅地退出Selenium WebDriver会话。
让我们在类级别声明WebDriver
,因为我们将在这两个方法中使用它,即setup()
方法用于启动驱动程序会话,以及tearDown()
方法用于优雅地退出会话。
public class TestJavaScriptExecutor {
private WebDriver driver;
//...
}
让我们创建一个新的setup()
方法,它将实例化一个WebDriver
类的实例,并相应地设置在本地Chrome浏览器上运行测试的配置。
public void setup () {
driver = new ChromeDriver ();
driver.manage ()
.window ()
.maximize ();
driver.manage ()
.timeouts ()
.implicitlyWait (Duration.ofSeconds (30));
}
该方法将打开Chrome浏览器,最大化其窗口,并应用30秒的隐式等待。这个隐式等待将允许所有网站内容在测试执行开始之前成功加载。

public void tearDown () {
driver.quit ();
}
最后,当测试执行时,将调用tearDown()
方法,它将优雅地关闭RemoteWebDriver会话。
现在让我们在同一个测试类中添加一个testJavaScriptExecutorCommand()
方法来实现我们讨论的测试场景。
public void testJavaScriptExecutorCommand () {
driver.get ("https://ecommerce-playground.lambdatest.io/index.php?route=account/login");
JavascriptExecutor js = (JavascriptExecutor) driver;
//....
}
该代码导航到LambdaTest eCommerce Playground网站的登录页面。下一行将WebDriver实例转换为JavascriptExecutor
,以便在浏览器中执行JavaScript命令。
WebElement emailAddressField = driver.findElement (By.id ("input-email"));
js.executeScript ("arguments[0].style.border='3px solid red'", emailAddressField);
emailAddressField.sendKeys ("[email protected]");
js.executeScript ("arguments[0].style.border='2px solid #ced4da'", emailAddressField);
接下来,它使用id
定位策略定位emailAddressField
。然后,它使用JavaScriptExecutor命令将电子邮件地址字段的边框突出显示为红色。
WebElement passwordField = driver.findElement (By.id ("input-password"));
js.executeScript ("arguments[0].style.border='3px solid red'", passwordField);
passwordField.sendKeys ("Password123");
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);
同样,登录按钮使用 CSS 选择器策略定位并进行了突出显示。
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);
接下来使用 JavaScriptExecutor 定位并在控制台上打印页面标题和域名。
String myAccountHeader = driver.findElement (By.cssSelector ("#content h2")).getText ();
assertEquals (myAccountHeader, "My Account");
最后,定位“我的账户”页面的页面标题,该页面在成功登录后显示,并执行断言来检查它是否显示文本“我的账户”。
以下是来自TestJavaScriptExecutor
类的完整代码:
public class TestJavaScriptExecutor {
private WebDriver driver;
public void setup () {
driver = new ChromeDriver ();
driver.manage ()
.window ()
.maximize ();
driver.manage ()
.timeouts ()
.implicitlyWait (Duration.ofSeconds (30));
}
public void tearDown () {
driver.quit ();
}
public void testJavaScriptExecutorCommand () {
driver.get ("https://ecommerce-playground.lambdatest.io/index.php?route=account/login");
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement emailAddressField = driver.findElement (By.id ("input-email"));
js.executeScript ("arguments[0].style.border='3px solid red'", emailAddressField);
emailAddressField.sendKeys ("[email protected]");
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 ("Password123");
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");
}
测试执行
以下来自 IntelliJ IDE 的截图显示了测试成功执行。

测试场景 2
我们的目标是编写一个简单的代码示例,使用executeAsyncScript()
方法来说明以下测试场景。
- 导航至LambdaTest 电子商务游乐场网站。
- 滚动到首页底部。
- 断言页面底部显示文本“FROM THE BLOG”。
实现:
在现有的TestJavaScriptExecutor
类中创建一个新的testExecuteAsyncScript()
方法。
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");
}
该代码将导航到LambdaTest eCommerce Playground网站的首页。接下来将调用JavaScriptExecutor的executeAsyncScript()
方法,在该方法中将执行滚动窗口的操作。
在executeAsyncScript()
方法中,执行的脚本需要通过调用提供的callback()
方法来明确地表示它们已经完成。
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeAsyncScript("var callback = arguments[arguments.length - 1];"
+ "window.scrollBy(0,document.body.scrollHeight); + callback()");
在滚动到窗口底部后,将定位到文本”FROM THE BLOG“,并对其执行断言。
String fromTheBlogText = driver.findElement(By.cssSelector("#entry_217991 > h3")).getText();
assertEquals(fromTheBlogText, "FROM THE BLOG");
测试执行
以下屏幕截图显示测试已成功执行。

在Selenium中使用JavaScriptExecutor的命令
让我们看一些可以使用JavaScriptExecutor接口来处理的Selenium测试自动化场景。
要单击按钮:
js.executeScript("document.getElementById('enter element id').click();");
//or
js.executeScript("arguments[0].click();", okButton);
在不使用sendKeys()
方法的情况下在文本框中输入文本:
js.executeScript("document.getElementById(id').value='someValue';");
js.executeScript("document.getElementById('Email').value='SeleniumTesting.com';");
通过传递true或false来处理复选框:
js.executeScript("document.getElementById('enter element id').checked=false;");
在Selenium WebDriver中生成警报弹出窗口:
js.executeScript("alert('Welcome To Selenium Testing');");
使用JavaScript刷新浏览器窗口:
js.executeScript("history.go(0)");
在Selenium中获取整个网页的innertext:
String innerText = js.executeScript(" return document.documentElement.innerText;").toString();
System.out.println(innerText);
获取网页的标题:
String titleText = js.executeScript("return document.title;").toString();
System.out.println(titleText);
获取域名:
String domainName= js.executeScript("return document.domain;").toString();
System.out.println(domainName);
获取网页的URL:
String url= js.executeScript("return document.URL;").toString();
System.out.println(url);
获取网页的高度和宽度:
js.executeScript(“return window.innerHeight;”).toString();
js.executeScript(“return window.innerWidth;”).toString();
使用JavaScript导航到不同页面:
js.executeScript("window.location = 'https://www.google.com");
在应用程序中使用Selenium执行滚动。
- 将页面垂直滚动500px:
Java
js.executeScript(“window.scrollBy(0,500)”);
- 垂直滚动页面直至末尾:
Java
js.executeScript(“window.scrollBy(0,document.body.scrollHeight)”);
在文档对象模型(DOM)中添加一个元素:
js.executeScript("var btn=document.createElement('newButton');"
+ "document.body.appendChild(btn);");
要在DOM中获取影子根:
WebElement element = driver.findElement(By.id("shadowroot"));
js.executeScript("return arguments[0].shadowRoot", element);
结论
Selenium具有称为JavaScriptExecutor的接口,当WebDriver命令不按预期行事时会被使用。借助JavaScriptExecutor,我们可以使用WebDriver在网站上执行JavaScript代码,从而以一种优雅且有效的方式处理各种任务,而仅使用Java则无法做到这一点。
在本博客中,我们探讨了如何在Selenium中使用JavaScriptExecutor及其不同的方法。此外,我们涵盖了各种场景,以及通过不同方法和实际示例获得有效解决方案的方法。
Source:
https://dzone.com/articles/how-to-use-javascriptexecutor-in-selenium