【问题标题】:Selenium Optimize getVisibleElement (when element is not present)Selenium 优化 getVisibleElement(当元素不存在时)
【发布时间】:2013-10-15 09:36:04
【问题描述】:

我正在使用 jBehave/Selenium 进行自动化测试。

现在我使用下面的代码来获取页面上的可见元素;

public WebElement getVisibleElement( final By by, final WebElement parentElement, int timeoutValue, TimeUnit timeoutPeriod, int pollingInterval, TimeUnit pollingPeriod ) {
       return fluentWait(timeoutValue, timeoutPeriod, pollingInterval, pollingPeriod).until( new Function<WebDriver, WebElement>(){
                public WebElement apply(WebDriver driver) {
                    try{
                        WebElement element = parentElement.findElement(by);
                        if ( element.isDisplayed() ) {
                            return element;
                        } else {
                            return null;
                        }
                    } catch( NoSuchElementException e ) {}

                    return null; 
                }
        } );
    }

现在的问题是,如果页面上不存在该元素,Selenium 会花费大量时间尝试在页面上找到它。 有什么办法可以优化代码,这样在这种情况下就不会花很长时间?

【问题讨论】:

标签: java selenium webdriver selenium-webdriver fluent


【解决方案1】:

甚至更优化的解决方案 - 是使用findElements(locator).size()...

    /**
     * Private method that acts as an arbiter of implicit timeouts of sorts.. sort of like a Wait For Ajax method.
     */
    private WebElement waitForElement(By by) {
        int attempts = 0;
        int size = driver.findElements(by).size();

        while (size == 0) {
            size = driver.findElements(by).size();
            if (attempts == MAX_ATTEMPTS) fail(String.format("Could not find %s after %d seconds",
                                                             by.toString(),
                                                             MAX_ATTEMPTS));
            attempts++;
            try {
                Thread.sleep(1000); // sleep for 1 second.
            } catch (Exception x) {
                fail("Failed due to an exception during Thread.sleep!");
                x.printStackTrace();
            }
        }

        if (size > 1) System.err.println("WARN: There are more than 1 " + by.toString() + " 's!");

        return driver.findElement(by);
    }

它的构建方式是在对其进行操作之前调用它。类似的,

WebElement myElement = waitforElement(By.cssSelector("input#someInput"));
myElement.sendKeys("something");

这是一个经过验证的解决方案,我已经在生产级回归测试系统中进行了测试和积极使用。

【讨论】:

  • 我没有看到这种方法比WebElement element = new WebDriverWait(driver, 10, 1000).until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#someElement")));有任何好处
【解决方案2】:

首先,我认为您不应该通过调用 findElement 并捕获潜在异常来检查元素的存在。最好使用 findElements 并检查列表大小

public WebElement getElementIfPresent(By locator) {
    driver.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
    List<WebElement> elements = driver.findElements(locator);
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    if(!elements.isEmpty()) {
        return elements.get(0);
    }
    else {
        return null;
    }
}

问题在于 WebDriver 会隐式等待元素出现。因此,在执行上述代码之前,您可能希望通过将隐式等待时间设置为较低值来缩短该时间。在您对可能不存在的元素进行任何查找之前,这需要是 dobe。然后需要恢复原来的隐式等待值,否则可能会影响剩余测试的稳定性。

最后,您只需使用 isDisplayed() 检查可见性,就像您在示例中所做的那样。

【讨论】:

  • 非常感谢...我只是想了解我应该将代码的第二部分放在哪里,即隐式等待 ....应该在检查 ....if( !elements.isEmpty()) { }
  • 不,不在 isEmpty() 之前。在您尝试查找元素之前需要对其进行检查,换句话说,在调用 findElement 之前。我已经编辑了我的答案以使其更清楚。
猜你喜欢
  • 1970-01-01
  • 2015-12-14
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多