【问题标题】:Webdriver executeScript sporadically not detecting dynamically generated elementsWebdriver executeScript 偶尔没有检测到动态生成的元素
【发布时间】:2014-09-24 17:22:24
【问题描述】:

我花了很长时间才弄清楚,但我仍然在努力解决这个问题。 我正在尝试使用 selenium webdriver 使用 javascript 注入访问网页上动态生成的元素。 例如:

 String hasclass = js.executeScript("return document.getElementById('additional-details').children[0].children[0].children["
                            + k + "].children[0].classList.contains(\"results-execs-name\")").toString();

现在,当我在 Firefox 控制台中执行此脚本时,它可以正常工作。但是当在 webdriver 5-6 中运行 10 次时,这条线会抛出异常(即使认为元素是物理存在的)。

为什么会这样?什么是解决方案?如果任何提示/答案有用,我一定会投赞成票。

编辑:

我已经放入了 Thread.sleep(500) ,甚至在我的代码中每次出现 executeScript() 之前等待 1000 秒。还是不行。

这是(部分)堆栈跟踪:

org.openqa.selenium.WebDriverException: document.getElementById(...).children[0].children[0] is undefined
Command duration or timeout: 169 milliseconds
Build info: version: '2.39.0', revision: 'ff23eac', time: '2013-12-16 16:12:12'
System info: host: 'rahulserver-PC', ip: '121.245.92.68', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_17'
Session ID: 747d2095-09f3-48b9-a433-59c5e334d430
Driver info: org.openqa.selenium.firefox.FirefoxDriver
Capabilities [{platform=XP, databaseEnabled=true, cssSelectorsEnabled=true, javascriptEnabled=true, acceptSslCerts=true, handlesAlerts=true, browserName=firefox, webStorageEnabled=true, nativeEvents=false, rotatable=false, locationContextEnabled=true, applicationCacheEnabled=true, takesScreenshot=true, version=31.0}]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:193)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
    at org.openqa.selenium.remote.RemoteWebDriver.executeScript(RemoteWebDriver.java:463)
    at Scraper.main(Scraper.java:62)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

【问题讨论】:

  • 失败时转储 HTML。检查它是否在那里。我还要说在我看来根本不需要 JS,您似乎正在检查特定元素(忽略它是某物的子元素的事实)是否具有特定的类。 Selenium 可以原生地做到这一点。
  • 这一次可能晚了,但您是否尝试过更长的睡眠时间来排除等待超时?也许 5 甚至 10 秒?我假设当您说您尝试“等待 1000 秒”时,您的意思是 1000 毫秒?您能否提供更多关于正在引入的动态元素的性质的信息?它就像一个由 AJAX 填充的可折叠树吗?脚本是否在循环中执行?注意到那里有一个“k”变量。

标签: java javascript selenium selenium-webdriver selenium-firefoxdriver


【解决方案1】:

关于检查 CSS 类:不需要为此执行脚本。您可以在纯 Java 代码中做到这一点。这对我有用:

String cssClass = driver.findElement(By.xpath(xpath)).getAttribute("class");
assertTrue(cssClass.contains("disabledentry"));

【讨论】:

    【解决方案2】:

    对于动态生成的列表,最好使用xPath来查找元素。

    为了更好的解决方案,您需要说明元素是在哪里动态生成的? 它可以在 tableul/li 等内部。

    1. 首先,找到父元素的xPath,即表格或列表项。
    2. 然后使用循环创建一个到元素位置的动态 xPath。代码sn-p如下:

      String xPath_1 = ".//li[@class='item drop-shadow tiny-shadow' and position()=";
      String xPath_2 = "]//div[@class='item-inner']//a";
      String finalxPath = xPath_1 + i + xPath_2;
      
    3. 创建一个名为 fluentWait 的方法来等待元素出现,而不是使用线程休眠。线程睡眠是不可靠的,它是测试失败的原因。 fluentWait 方法也会忽略 NoSuchElementException(您可以在列表中添加更多内容,例如 StateStateElementException)。代码sn-p如下:

      public void fluentWait(final By by)
      {
          FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                 .withTimeout(60, TimeUnit.SECONDS)
                 .pollingEvery(5, TimeUnit.SECONDS)
                 .ignoring(NoSuchElementException.class);
             WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
               public WebElement apply(WebDriver driver) {
                 return driver.findElement(by);
               }
             });
      }
      
    4. 然后用你动态生成的xPath调用这个方法,如下:

      fluentWait(By.xpath(finalxPath ));
      

    要学习 xPaths,您可以使用以下Tutorial。你可以试试这个并告诉我。干杯

    【讨论】:

      【解决方案3】:

      使用 Selenium,您必须始终注意,脚本执行可能需要一点时间。如果您遇到有时成功有时失败的情况,请检查 Thread.sleep(500) 是否对您有帮助。否则 JUnit 可能会在脚本完成之前评估断言。

      【讨论】:

      • 好的,抱歉没能帮到你
      • 如果您可以指定更详细的错误信息(例如堆栈跟踪),这可能是一个线索
      • 这显然看起来好像指定的元素不存在。确保您的脚本具有预期的结果并且不会静默失败或吞下错误(严格模式开启?始终在 JS 中使用严格模式)。也许 children[0].children[0] 有点通用。如果可能,您应该使用 jQuery 进行 DOM 操作以避免编程错误。
      • 如何在 webdriver 中开启严格模式?它是可配置的吗?并且关于dom解析,它是正确的。我通过 Firefox 控制台确认。
      • 你可以通过输入“use strict”来开启严格模式;作为 JS 脚本中的第一条语句
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多