【发布时间】:2012-12-09 06:50:12
【问题描述】:
我正在使用 Selenium WebDriver (Java) 和 TestNG 在我创建的网站上进行一些测试。在这个网站,我也有JavaScript,在一些函数中,它通过console.log()返回值并输出值到浏览器控制台。
我想知道 Selenium WebDriver 是否有一种简单的方法可以访问这些 JavaScript 信息,以便我可以使用 TestNG 执行断言。
我对 Selenium 很陌生,但我知道您可以执行以下操作:
WebDriver driver = new ChromeDriver();
driver.findElement(By.id("btn")).click();
那么我可以使用WebDriver 来读取网站上的 JavaScript 吗?
澄清
看起来人们假设我正在尝试通过 Selenium “执行” JavaScript 代码。
事实并非如此。相反,我尝试使用 Selenium 存储已定义的 JavaScript 变量。
基本上,我希望 Selenium 能够获取 JavaScript 变量的值,将其存储在本地,然后对其进行断言测试。
尝试 1
假设我的网站有以下 JS 代码:
$(document).ready(function() {
var foo = $(#"input-field-val").val();
function returnFoo() {
return foo;
}
});
根据我的阅读和理解,在我单独的 Selenium 测试文件 (Selenium.java) 中,我应该能够做这样的事情吗?:
public class Selenium {
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
@Test
public void testSample() {
driver.get("www.mywebsite.com");
js.executeScript("alert(returnFoo());");
}
}
我做了与上面类似的事情,但没有弹出警告框。相反,我收到一条错误消息:
Exception in thread "main" org.openqa.selenium.WebDriverException: ReferenceError: returnFoo is not defined
我很确定我不明白它说 JS 变量是什么意思
不应是闭包或局部变量的一部分
我也试过在$(document).ready(function()...上方定义一个全局变量,设置在function returnFoo()内,但还是不行。
尝试 2
我已将foo 和returnFoo() 移出$(document).ready(function()...。这已经修复了我在上述尝试 1 中收到的 ReferenceError 消息。
我还给了foo 一个值,所以我的 JS 代码看起来像这样:
var foo = "Selenium test run";
$(document).ready(function() {
...
});
function returnFoo() {
return foo;
}
现在,我很难将 returnFoo() 的返回值分配给我的 Selenium 测试中的局部变量。这是我尝试过的:
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
driver.get("http://localhost:8080/HTML5TestApp/prod.html");
Object val = js.executeScript("window.returnFoo();");
System.out.println(val);
}
但是控制台显示null而不是“Selenium test run”的实际值。
尝试 2 - 解决方案
看起来如果我执行Object val = js.executeScript("alert(returnFoo());"); 会得到foo 的值。
解决方案
感谢下面 Martin Foot 的解决方案,这是我针对我的问题提出的解决方案。
在我的 JavaScript 文件中,我创建了一个 var 和一个 setter/getter 函数,如下所示:
index.js
var seleniumGlobal;
$(document).ready(function() {
...
)};
function setSG(toSet) {
seleniumGlobal = toSet;
}
function getSG() {
return seleniumGlobal;
}
SampleTest.java
// Do all the necessary imports
public class SampleTest {
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
@Test
public void testPrintVal() {
String sgVal = (String) js.executeScript("alert(getSG());");
Assert.assertEquals("new value for seleniumGlobal", sgVal);
}
}
因此,每当我的 JavaScript 中的某些代码通过 setter 方法设置我的 seleniumGlobal 变量时,我就可以通过我的 Selenium 测试调用它并对其进行断言。
这可能不是最有效的方法,但如果其他人有更好的解决方案,请告诉我。
【问题讨论】:
-
有点老了,但我建议你看看我的解决方案。我的一些同事偶然发现了这个页面并且正在执行警报“hack”,实际上你应该只返回值,正如你在下面的答案中看到的那样:)
-
简单:
executeScript("return globalVar;") -
@wTyeRogers 这里
return关键字的目的是什么?如果你把它写到控制台中,它会抛出错误。 Selenium 对这个命令所做的工作相当于人类的什么?
标签: javascript selenium testng selenium-webdriver