【问题标题】:Selenium (Java) Correctly using explicit waits with PageFactorySelenium (Java) 正确使用 PageFactory 的显式等待
【发布时间】:2020-07-13 17:36:31
【问题描述】:

查看 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 驱动程序保持到等待指定的条件发生?

【问题讨论】:

  • 这并不是你“将它们分配给一个元素”......而是 webdriverwait 将返回一些东西或抛出。如果你不需要它,你不需要存储它。无论哪种方式,它都会等到满足预期条件。不同的预期条件有不同的类型,这就是返回的内容。 (最常见的是bool或webelement):selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/…

标签: selenium selenium-webdriver webdriver webdriverwait expected-condition


【解决方案1】:

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

public void isLoaded() 抛出错误 { // 初始加载,在创建页面对象时调用,以确保页面加载到准备好与我们交互的状态,在我们的例子中,这意味着按钮存在于 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 中定义了等待,以实现 waitForVisibility 代码在所有页面对象类中的可重用性。

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

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

    buttonSubmit.click();
    waitForVisibility(alertPopup);

【讨论】:

    【解决方案2】:

    有几件事:

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

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

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

      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")));
      

    您可以在How to add explicit wait in PageFactory in PageObjectModel?找到相关的详细讨论

    【讨论】:

      【解决方案3】:

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

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

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

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

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

      contactUsPage.sendMessageForm();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-24
        • 2019-07-07
        • 2023-03-11
        • 2021-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多