使用 Selenium WebDriver 读取 JavaScript 变量

Posted

技术标签:

【中文标题】使用 Selenium WebDriver 读取 JavaScript 变量【英文标题】:Reading JavaScript variables using Selenium WebDriver 【发布时间】: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

我已将fooreturnFoo() 移出$(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 对这个命令所做的工作相当于人类的什么? 【参考方案1】:

你所要做的就是:

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

这将为您提供所需的内容。

【讨论】:

对于那些使用 Ruby 的人,一个例子是val = driver.execute_script("return $('#something').offset().left") 您的解决方案正是我想要的。非常感谢【参考方案2】:

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

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

对于 Python:

result = driver.execute_script("return globalVar")

【讨论】:

【参考方案3】:

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

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

【讨论】:

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

以上是关于使用 Selenium WebDriver 读取 JavaScript 变量的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用 selenium webdriver 读取浏览器 url 吗?

在 selenium webdriver 中从 Flash 播放器读取内容

使用 Flash 播放器加载图形时如何使用 selenium webdriver 处理图形和读取图形数据

使用`selenium-webdriver-webelement.send_keys`遇到的问题

selenium+requests进行cookies保存读取操作

使用 Selenium WebDriver for Firefox 下载 pdf