0

在查看了 selenium 文档之后,我想知道我是否试图错误地实现显式等待。

在文档中,它总是显示识别一个新元素,然后将定义的等待分配给所述元素

WebDriver driver = new ChromeDriver();
driver.get("https://google.com/ncr");
driver.findElement(By.name("q")).sendKeys("cheese" + Keys.ENTER);
// Initialize and wait till element(link) became clickable - timeout in 10 seconds
WebElement firstResult = new WebDriverWait(driver, Duration.ofSeconds(10))
        .until(ExpectedConditions.elementToBeClickable(By.xpath("//a/h3")));
// Print the first result
System.out.println(firstResult.getText());

在此示例中,创建了一个新元素 firstResult,然后为其分配了定义的等待。

这是必需的吗?应该总是这样吗?

这就是我问的原因。

我正在使用 PageFactory 模型并通过 FindBy 注释定义我的元素,如此处所示。

// Input field for slice ID
@FindBy(how = How.XPATH, using = "//input[@name='id']")
private WebElement inputSliceId;

然后,在同一个类中,我定义了一些方便的方法来使用它们。

所以现在,在我的方便方法中,我应该做这样的事情吗?

inputSliceId = new WebDriverWait(driver, Duration.ofSeconds(10))... 
inputSliceId.sendKeys(...

我一直在做的事情,也就是我现在要质疑的事情,是放置未直接分配给相关元素的等待语句。

例如,我一直在做这样的事情。

buttonSubmit.click();
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@role='alertdialog']")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@role='alertdialog']")));

为什么?(这里可能完全错了)

单击按钮后,我需要等待弹出窗口显示一旦出现,我就等待它消失,然后再继续

这是主要问题 这两条等待线是否真的没有做任何事情,因为我没有将它们分配给一个元素?还是它们仍然导致 Web 驱动程序保持到等待指定的条件发生?

4

3 回答 3

1

有几件事:

  • getText()如果您的用例是在一个元素上调用,而不是elementToBeClickable(), usingvisibilityOfElementLocated()将是完美的。
  • 要提取文本,您不必创建任何新元素,而是可以visibilityOfElementLocated()在元素返回后直接调用,如下所示:

    System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//a/h3"))).getText());
    
  • 如果您的用例不包含对显示和消失的弹出窗口的任何验证,则您无需为它诱导任何服务员并安全地忽略它。因此,一旦您调用click()buttonSubmit您就可以进入下一个验证点,调整弹出窗口显示和消失的时间跨度。

  • 因此,您优化的代码块将是:

    buttonSubmit.click();
    // consider the total timespan for the wait to be cumulative of: pop-up displayed + pop-up disappear + next interactable element to become clickable
    new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.elementToBeClickable(By.xpath("xpath_next_element_to_click")));
    

您可以在如何在 PageObjectModel 中的 PageFactory 中添加显式等待中找到相关的详细讨论?

于 2020-04-01T22:38:08.540 回答
1

不,您不能将上述等待语句分配给您的网络元素。如果你想使用页面工厂模型等待你的元素,那么你必须创建

public void isLoaded() throws Error { // 初始加载,在创建页面对象时调用,以确保页面加载到准备好与我们交互的状态,在我们的例子中,这意味着按钮存在于 DOM并且可见。

public class BaseClass
{
     private void waitForVisibility(WebElement element) throws Error{
               new WebDriverWait(driver, 60)
                    .until(ExpectedConditions.visibilityOf(element));
        }
}

然后在您的页面对象模型类中,您可以扩展此BaseClass

public class page extends BaseClass

{
    @FindBy(how = How.XPATH, using = "//input[@name='id']")
    private WebElement inputSliceId;

    waitForVisibility(inputSliceId);

}

我在 BaseClass 中定义了 wait 以实现 waitForVisibility 代码在所有页面对象类中的可重用性。

同样在单击按钮后,如果您想等待弹出窗口出现,那么您可以包含如下代码:

    @FindBy(xpath = "//div[@role='alertdialog']")
    private WebElementFacade alertPopup;

    buttonSubmit.click();
    waitForVisibility(alertPopup);
于 2020-04-01T20:52:04.873 回答
0

首先,您可以在一个单独的类(如基类或父类)中声明一个设置等待本身的方法,如下所示:

protected void waitForElementToBeLoaded(WebElement element) {
 wait.until(ExpectedConditions.elementToBeClickable(element));
}

然后,您可以在像虚构页面一样使用的单独类中声明使用第一个方法的第二个方法,如下所示:

public void sendMessageForm( ){
    waitForElementToBeLoaded(sendBtn);
    sendBtn.click();
}

最后,每次使用前面的方法都会触发等待,例如:

contactUsPage.sendMessageForm();
于 2020-04-02T00:21:06.793 回答