WebDriver 不能可靠地单击链接或按钮

2022-01-14 00:00:00 automated-tests webdriver java

我一直在拼命想让 WebDriver 可靠地单击按钮或链接,但它就是不想合作.我尝试了不同的方法,从设置隐式超时到下面的代码,假设单击并等待元素出现.

I have been desperately trying to get WebDriver to click a button or link reliably, but it just does not want to cooperate. I have tried different methods from setting an implicit timeout, to the below code which is suppose to click and wait for the element to appear.

下面的代码片段是在互联网上的某个地方找到的,它是我最接近可靠地获得一个按钮或链接来点击的地方.除了它在调试模式下的工作方式与我在夜间回归测试期间执行时的工作方式不同.

The below snippet of code was found somewhere on the internet, and it the closest I have come to reliably getting a button or link to click. Except it does not work the same in debug mode as it does when executed during my nightly regression testing.

有谁知道在浏览器中单击按钮或链接的另一种方法?或者我应该使用 Selenium 1 而不是 WebDriver,因为它太新而无法可靠使用.

Does anyone know of another method to click a button or link in a browser? Or should I be using Selenium 1 and not WebDriver as it is too new to be used reliably.

public void waitAndClick(WebDriver driver, By by) {
    WebDriverWait wait = new WebDriverWait(driver, 10000, 2000);
    Function<WebDriver, Boolean> waitForElement = new waitForElement(by);
    wait.until(waitForElement);

    Actions builder = new Actions(driver);
    builder.click(driver.findElement(by))
            .perform();
}

private class waitForElement implements Function<WebDriver, Boolean> {
    private final By by;

    private String text = null;

    public waitForElement(By by) {
        this.by = by;
    }

    public waitForElement(By by, String text) {
        this.by = by;
        this.text = text;
    }

    @Override
    public Boolean apply(WebDriver from) {
        if (this.text != null) {
            for (WebElement e : from.findElements(this.by)) {
                if (e.getText().equals(this.text)) {
                    return Boolean.TRUE;
                }
            }

            return Boolean.FALSE;
        } else {
            try {
                driver.switchTo().defaultContent().switchTo().frame("top");
                from.findElement(this.by);
            } catch (Exception e) {
                logger.error("Unable to find "" + this.by.toString() + "". Retrying....");
                return Boolean.FALSE;
            }
            logger.info("Found "" + this.by.toString() + "".");
            return Boolean.TRUE;
        }
    }
}

在 Eclipse 调试模式下控制台输出:

Console out in Eclipse Debug mode:

16:07:08,109 INFO  WebDriverUtility: apply Found "By.linkText: Classes".
16:07:10,514 INFO  WebDriverUtility: apply Found "By.linkText: Reports".
16:07:17,028 ERROR WebDriverUtility: apply Unable to find "By.linkText: Users". Retrying....
16:07:26,369 INFO  WebDriverUtility: apply Found "By.linkText: Users".
16:07:38,272 ERROR WebDriverUtility: apply Unable to find "By.linkText: System". Retrying....
16:07:41,334 INFO  WebDriverUtility: apply Found "By.linkText: System".
16:07:47,722 ERROR WebDriverUtility: apply Unable to find "By.linkText: Schools". Retrying....
16:07:50,565 INFO  WebDriverUtility: apply Found "By.linkText: Schools".

从 Eclipse 运行时控制台退出:

Console out when running from Eclipse:

16:14:04,179 INFO  WebDriverUtility: apply Found "By.linkText: Classes".
16:14:04,726 INFO  WebDriverUtility: apply Found "By.linkText: Reports".
16:14:09,771 INFO  PageAPITesting: login org.openqa.selenium.NoSuchElementException: Unable to find element with link text == Reports (WARNING: The server did not provide any stacktrace information)
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '2.0rc3', revision: '12536', time: '2011-06-20 18:19:52'
System info: os.name: 'Windows XP', os.arch: 'x86', os.version: '5.1', java.version: '1.6.0_24'
Driver info: driver.version: RemoteWebDriver
16:14:09,865 INFO  PageAPITesting: login current tabs is Classes
16:14:09,958 INFO  WebDriverUtility: apply Found "By.linkText: Schools".
16:14:10,240 INFO  PageAPITesting: login java.lang.IllegalStateException: Unable to navigate to the ca.schoolspecialty.qa.api.pages.schools.MenuSchoolPage page

推荐答案

我没有看到任何奇怪的行为,

I don't see any strange behavior,

wait.until 方法,它的作用是在函数上调用apply 方法,直到它返回一些东西或者有一个Time Out.

The wait.until method, what it does is to call the apply method on the function until it returns something or there is a Time Out.

如果元素尚未创建,则有时会收到 NotFoundExceptions,实际上,如果您查看代码,您会看到:

It's expected to receive NotFoundExceptions sometimes if the element hasn't been created yet, actually if you look in the code you'll see this:

 while (clock.isNowBefore(end)) {
  try {
    T value = isTrue.apply(driver);

    if (value != null && Boolean.class.equals(value.getClass())) {
      if (Boolean.TRUE.equals(value)) {
        return value;
      }
    } else if (value != null) {
      return value;
    }
  } catch (NotFoundException e) {
    // Common case in many conditions, so swallow here, but be ready to
    // rethrow if it the element never appears.
    lastException = e;
  }
  sleep();

它捕获异常并且什么都不做,问题是您覆盖了应用程序以捕获并记录该异常,所以您看到的是预期的行为,没有其他方法可以检查元素是否已创建不断地要求它.

It catches the exception and does nothing with it, the problem is that you overwrote the apply to catch and logs that exception, so what you are seeing is the expected behavior, there's no other way to check if the element has been created that continuously asking for it.

我自己正在将这段代码用于函数生成器:

I myself I'm using this code for the Function generator:

public static Function<WebDriver, WebElement> presenceOfElementLocated(
        final By locator) {
    return new Function<WebDriver, WebElement>() {
        @Override
        public WebElement apply(WebDriver driver) {
            return driver.findElement(locator);
        }
    };
}

更简单,您可以用于任何定位器

Is a lot simpler and you can use for any Locator

相关文章