如何在没有 By 定位器的情况下使用 WebDriverWait.until?

How to use WebDriverWait.until without a By locator?

我正在使用通过框架 (Cucumber) 实现的 Selenium WebDriver,但在执行操作之前等待元素加载时遇到了问题。

最初,我想使用隐式等待,但如果一个元素没有立即加载,它就会等待超时。通常情况下,它使我的测试时间比我想要的要长。

然后,我想使用 Explicit wait 使每种情况的等待时间尽可能短。 问题是 WebDriverWait.until 中的大多数 ExpectedConditions 正在寻找由 By 定位器定位的元素(它们是 ClassName、CssSelector、Id、LinkText、Name、PartialLinkText、Tagname 或 XPath)。 我在用于单击网络元素的通用函数中使用 WebDriverWait.until。 我正在测试的网站上的 Webelements 是由 dojo 生成的,没有静态 ID。它们并不总是有其他类型的定位器,或者它们不是静态的。 然后,开发人员向网络元素添加了一个名为 data-automation-id 的附加属性。我想在显式等待中使用此属性,但找不到方法。

我尝试使用以下代码来使用 xpath :

public void clickOnDataAutomationId(String dataautomationid) {
    WebDriverWait wait = new WebDriverWait(driver, 10);
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//" + findDataAutomationId(dataautomationid).getAttribute("tagName") + "[contains(@data-automation-id, '" + dataautomationid + "')]")));
    findDataAutomationId(dataautomationid).click();
}

findDataAutomationId() 是一个函数,它返回第一个包含 data-automation-id 作为 FluentWebElement 的网络元素。

问题是如果没有立即加载网络元素,findDataAutomationId 会失败,这使得 WebDriverWait.until 变得毫无意义。您是否看到另一种无需重构网站即可解决“按定位器”问题的方法?

使用 "presenceOfElementLocated" 方法代替 "elementToBeClickable"。此更改可能会帮助您

与其使用方法findDataAutomationId检索webelement,不如直接找到webelement,然后点击如下图:

public void clickOnDataAutomationId(String dataautomationid) {
   WebDriverWait wait = new WebDriverWait(driver, 10);
   WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(@data-automation-id, '" + dataautomationid + "')]")));
   element.click();
} 

或者,如果data-automation-id是一个完整的文本而不是一个部分,那么你可以使用下面的代码:

public void clickOnDataAutomationId(String dataautomationid) {
   WebDriverWait wait = new WebDriverWait(driver, 10);
   WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@data-automation-id, '" + dataautomationid + "')]")));
   element.click();
}

你下面的解决方案。它不会 return 直到 apply() 为真或直到等待超时

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(new Function<WebDriver, Object>() {
                @Nullable
                public Object apply(@Nullable WebDriver input) {
//add any condition or check your data-automation-id is visible/clickable
                    return true; 
                }
            });
    }