【问题标题】:Webdriver, detect DOM changing and wait for itWebdriver,检测 DOM 变化并等待它
【发布时间】:2013-12-02 08:47:30
【问题描述】:

我在 Java 中使用 Webdriver,但我反复遇到一个问题,我还没有找到合适的解决方案。

这与在页面上执行会导致该页面 DOM 更改的操作有关(例如,Javascript 灯箱),然后我的 JUnit 测试在 DOM 更改后期待新元素,但我的测试正在获取旧的 DOM 元素.

举个例子,我有一个场景如下。

首先点击下图中的“添加项目”按钮,出现灯箱:

然后填写所有项目详细信息,然后单击“添加并关闭”。您将看到以下屏幕:

请注意,现在有一条信息消息Your item ... has been added

现在我在搜索文本框中输入关键字并按回车键,信息消息将更改为以下内容:

在我的 JUnit 测试中,流程如下:

....
    itemDetailsPage.clickAddAndClose();
    itemDetailsPage.searchItemBy("Electricity");
    assertEquals("Your search for 'electricity' returned 2 results.",
        itemDetailsPage.getInfoMsg());
....

现在这个测试不是很健壮,因为如果网络很慢,大多数时候getInfoMsg() 会返回之前的信息消息Your item ... has been added 而不是最新的信息消息,这会导致测试失败。请注意,这两条信息消息共享相同的 html 元素 ID。

我在这里尝试实施的解决方案是:

  1. 在 clickAddAndClose() 中添加显式等待 所以它看起来像:

    public void clickAddAndClose() {
        ...
        clickWhenReady(driver, By.id(addAndCloseButtonId));
        ...
        waitForElementByLocator(driver,By.id(itemInfoMsgId),10);
    }
    

    第二次等待被证明是无用的,因为itemInfoMsgId 在用户从添加项目灯箱添加项目时已经存在。

  2. clickAddAndClose() 末尾添加waitForPageLoaded() 方法以尝试等待页面完成重新加载。 waitForPageLoaded() 的通用方法如下:

    public void waitForPageLoaded(WebDriver driver) {
        ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver driver) {
                return ((JavascriptExecutor) driver).executeScript(
                "return document.readyState").equals("complete");
            }
        };
        Wait<WebDriver> wait = new WebDriverWait(driver, 30);
        try {
            wait.until(expectation);
        } catch (Throwable error) {
            assertFalse("Timeout waiting for Page Load Request to complete.",
            true);
        }
    }
    

我预计在clickAddAndClose() 的末尾,它会看到此页面仍在更新,因此它会等到信息消息更新。但这似乎也不起作用。

这让我最后的选择是在clickAddAndClose() 的末尾添加一个线程睡眠。我想避免使用它。

有解决这类问题的通用方法吗?如何检测页面 DOM 仍在变化并告诉 Webdriver 等到它完成刷新?

【问题讨论】:

  • 尝试在预期条件下使用stalenessOf 方法。当元素不再存在于 DOM 中时,它返回 True。之后使用你的第二个等待语句

标签: java selenium webdriver selenium-webdriver


【解决方案1】:

如果(看起来确实如此)您的页面正在被 AJAX 操作修改,则等待页面加载将不起作用。

不要等待页面加载,而是等待您正在测试的条件变为真。这样,您就可以给 AJAX 操作时间来执行,如果出现问题,您将在超时发生时收到错误消息。

我通常使用 Selenium 的 Python 绑定,自从我编写 Java 代码以来已经有一段时间了,但我相信它看起来像这样,X 被替换为适合 itemDetailsPage 对象的类型:

new FluentWait<X>(itemDetailsPage)
    .until(new Function<X, Boolean>() {
        public Boolean apply(X itemDetailsPage) {
            return "Your search for 'electricity' returned 2 results." == itemDetailsPage.getInfoMsg();
        };
    });

【讨论】:

  • 嗨,路易斯,非常感谢您的解决方案。是的,从外观上看,这可以工作,但这不是一个理想的解决方案。原因是因为我不认为在等待消息中硬编码是一个理想的解决方案,因为这只是众多场景之一。在测试用例中,我根本没有等待,所以我唯一可以把它放在页面对象中的地方。
  • 没有必要在apply 方法中硬编码预期的字符串。
【解决方案2】:

似乎你需要等到 ajax 完成它的工作。在类似的情况下,我使用了类似于here 中描述的 waitForJQueryProcessing 的方法。看看吧,或许会有帮助。

【讨论】:

  • 我尝试了您的waitForJQueryProcessing 方法并出现以下错误:org.openqa.selenium.WebDriverException: jQuery is not defined 命令持续时间或超时:15 毫秒
  • This question 可能是相关的。请参阅 Ardesco 那里的答案。
猜你喜欢
  • 1970-01-01
  • 2012-06-18
  • 2021-06-07
  • 1970-01-01
相关资源
最近更新 更多