使用 Selenium WebDriver 读取 JavaScript 变量

IT技术 javascript selenium testng selenium-webdriver
2021-03-09 07:37:05

我正在使用 Selenium WebDriver (Java) 和 TestNG 在我创建的网站上进行一些测试。在这个网站中,我也有 JavaScript,并且在一些函数中,它返回值并通过 .js 将值输出到浏览器控制台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

我既感动fooreturnFoo()外面的$(document).ready(function()...这已经修复ReferenceError了我在上面的尝试 1中得到的消息

我还给出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 函数,如下所示:

索引.js

var seleniumGlobal;

$(document).ready(function() {
...
)};

function setSG(toSet) {
    seleniumGlobal = toSet;
}

function getSG() {
    return seleniumGlobal;
}

示例测试.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 中的某些代码seleniumGlobal通过 setter 方法设置我的变量时,我都可以通过我的 Selenium 测试调用它并对其进行断言。

这可能不是最有效的方法,但如果其他人有更好的解决方案,请告诉我。

3个回答

您所要做的就是:

Object val = js.executeScript("return returnFoo();");

这会给你你正在寻找的东西。

您的解决方案正是我正在寻找的。非常感谢
2021-04-19 07:37:05
对于那些使用 Ruby 的人,一个例子是 val = driver.execute_script("return $('#something').offset().left")
2021-04-22 07:37:05

不需要定义 JavaScript 函数。也不alert()需要。

Object result = js.executeScript("return globalVar");

对于 Python:

result = driver.execute_script("return globalVar")

在 Ruby 中,您可以page.execute_script用来评估 JavaScript 变量(如果它可以从 Web 浏览器的范围内访问)。看起来Java here 中也有类似的方法

编辑:这可能是一个更适合 JavaScript 单元测试框架(例如Jasmine )的用例

我的意思是您正在访问的变量不是闭包或局部变量的一部分。IE 可以通过 window 对象的某个路径访问它。如果在您的控制台中我可以看到 window.bla.bla.yourvariable,您可以从 execute_script 访问它。否则,您将需要手动设置它。如果是这种情况,JS 单元测试会更好。从窗口范围访问事物通常是不好的。
2021-04-16 07:37:05
Martin 在这两方面都是对的:您绝对可以通过(任何语言的)Selenium Webdriver 运行任意 Javascript 代码。但是,Selenium 有许多……不太理想的方面,因此您可能会发现除非绝对必须(即仅用于功能和集成测试),否则您不想使用它。对于 Javascript 单元测试(和一些集成测试),我强烈建议使用 JS 测试框架。Martin 提到了 Jasmine,QUnit 也很受欢迎,但如果你想要一个类似 JUnit(或 TestNG)的命令行测试运行器,我推荐 JS-Test-Driver 或 Buster。
2021-04-23 07:37:05
Jasmine 还报告了一个 JUnit 兼容测试,我将其用于 CI 构建:) 编辑:虽然设置起来有点麻烦!
2021-04-27 07:37:05
谢谢。我会仔细看看JavascriptExecutor. 当您说“如果它可以从网络浏览器的范围内访问”时,您的意思是只要网页通过<script type="text/javascript"...w/i导入它<HEAD>
2021-05-09 07:37:05
顺便说一句,所有这些 JS 测试框架都将在真实浏览器中运行,为您提供与 Selenium 相同的“真实世界”好处(而不是说运行无头 Nose 测试)。然而,它们的运行时间不会像 Selenium 测试一样长,也不会遇到 Selenium 的其他问题(例如,无缘无故地随机停止测试)。
2021-05-13 07:37:05