【问题标题】:Can JavaScript talk to Selenium 2?JavaScript 可以与 Selenium 2 对话吗?
【发布时间】:2011-08-01 18:50:53
【问题描述】:

我知道我可以让 Selenium 2 的 webdriver 运行 JavaScript 并获取返回值,但是发生了太多异步的事情,我希望 JavaScript 与 Selenium 对话,而不是相反。我做了一些搜索,但没有找到类似的东西。人们通常只使用implicitly_wait吗?这似乎可能会失败,因为不可能为所有事情计时?完美的例子是让 Selenium 知道 XHR 何时完成或执行时间不确定的异步动画。

这可能吗?我们在 Saucelabs 上使用 Selenium 2 和 Python。

【问题讨论】:

    标签: javascript python asynchronous selenium selenium-webdriver


    【解决方案1】:

    您应该查看 execute_async_script() 方法(Java 中的 JavascriptExecutor.executeAsyncScript,.NET 中的 IJavaScriptExecutor.ExecuteAsyncScript()),它允许您等待回调函数。回调函数会自动附加到 JavaScript 函数中的 arguments 数组。因此,假设您的页面上已经有一个 JavaScript 函数等待您想要的条件,您可以执行以下操作(下面的 Java 代码,C# 和 Python 代码应该相似):

    String script = "var callback = arguments[arguments.length - 1];"
        + "callback(myJavaScriptFunctionThatWaitsUntilReady());";
    
    driver.manage().timeouts().setScriptTimeout(15, TimeUnit.SECONDS);
    ((JavascriptExecutor)driver).executeAsyncScript(script);
    

    可能会更聪明,将回调函数直接传递给返回正确数据的事件。您可以在项目JavaDocs 中找到有关 executeAsyncScript() 函数的更多信息,并且可以在项目源代码树中找到这方面的示例代码。在this file 的测试中有一个等待 XHR 完成的很好的例子。

    如果可用于 SauceLabs 的 Python 绑定版本中尚不提供此功能,我希望它很快就会可用。诚然,从某种意义上说,这是将“对所需状态的轮询”从您的测试用例推送到 JavaScript 中,但它会使您的测试更具可读性。

    【讨论】:

      【解决方案2】:

      理论上是可能的,但我建议不要这样做。

      解决方案可能会在站点上运行一些 jQuery,当 JavaScript 处理完成时将变量设置为 true。

      将 selenium 设置为循环通过 getEval 直到此变量变为 true,然后在 Selenium 中执行某些操作。

      它会满足您的要求,但这是一个非常糟糕的主意。如果由于某种原因您的 jQuery 没有将 trigger 变量设置为 true(或您期望的任何状态),Selenium 将无限期地坐在那里。您可以对其设置很长的超时时间,但是让 Selenium 执行 getEval 并等待特定元素出现会有什么不同?

      听起来您正试图过度设计您的解决方案,这将在未来给您带来更多痛苦,而额外的好处却很少。

      【讨论】:

      • 您建议使用 Selenium 进行轮询,这不是一回事。我想知道 Selenium 是否有任何它添加到站点的钩子。我很惊讶它没有。甚至 Flash 在 Flash 外部也有这个。
      • Selenium 不会修改站点,它只是查看 DOM 和 HTML。您可以做您想做的事情的唯一方法是通过某种方式操作 DOM,然后让 Selenium 检查 DOM 以进行更改。你不能从你的网站驱动 selenium。
      • 您无法从您的网站驱动 selenium。那就是我的答案。我认为它应该这样做,但没有。谢谢!
      【解决方案3】:

      不要太直率,但如果您希望您的应用程序与您的测试运行程序对话,那么您做错了。

      如果您需要等待 XHR 完成,您可以尝试显示一个微调器,然后测试微调器是否消失以表明请求成功。

      关于动画,当动画完成时,它的回调可能会添加一个表示动画已经完成的类,然后您可以测试该类是否存在。

      【讨论】:

      • 在这两种情况下,您都忽略了计时部分。 JavaScript 是异步的。我不是在问如何让 Selenium 检查事物,而是在问如何判断何时检查。一个你没有回答的问题。由于 JavaScript 是异步的,因此最好的时间是 JavaScript 准备就绪的时候,只有 JavaScript 知道什么时候准备就绪。钩子是最好的方法。那么有吗?
      • 根据我使用 Selenium 1 和 2 的经验,您的测试会在您的应用程序中触发异步调用。然后使用 wait_for 命令等待元素存在(或不存在)。如果您编写应用程序以期望 Selenium 存在,那么我认为您正在错误地解决问题。您的应用程序不应该关心 Selenium 或任何其他测试框架。这使您可以在将来有更好的结果时更换测试运行器。
      • 也许这是一个更好的答案:您告诉 Selenium 在触发异步操作后立即进行检查。然后,Selenium 将等待一段时间以使该条件存在。如果在分配的时间内不存在,则假定操作失败,因此测试应该失败。
      • 我正在寻找相同的功能。我的想法是让 javascript 在完成后引发一个事件,并在 selenium 中侦听此类事件,可能通过 webdriver 启动的 javascript。由于我对 javascript 的经验有限,我不确定这是否可行。事件机制将避免硬依赖问题,但它当然需要原始 javascript 提供事件,这可能意味着更改代码。
      • 我不认为你理解我。我知道脚本正在执行并立即返回。您需要测试的是异步请求已完成的视觉指示器。这通常是通过显示一个微调器图形来完成的,该图形向用户指示正在发生的事情。在 Selenium 中,您将测试微调器不再可见。
      【解决方案4】:

      用 selenium 测试动画是打开一罐蠕虫。测试可能非常脆弱并导致许多误报。

      问题在于调用是异步的,很难跟踪页面的行为和状态变化。

      根据我的经验,异步调用可能非常快,以至于永远不会显示微调器,并且页面的状态可能会完全跳过一个状态(Selenium 可以检测到)。

      等待页面状态转换可以使测试不那么脆弱,但是不能完全消除误报。

      我建议对动画进行手动测试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-14
        • 2021-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-10
        相关资源
        最近更新 更多