【问题标题】:Robust solution for verify error messages on the page with Java+Selenium WebDriver使用 Java+Selenium WebDriver 验证页面上的错误消息的强大解决方案
【发布时间】:2018-02-05 19:29:04
【问题描述】:

情况:给定一个连接到外部系统的复杂 webapp。如果外部系统出现故障,可能有 2 个选项。

  1. 案例:出现 div 中的大胖堆栈跟踪。定位器 div 类:errorPage

  2. 案例:应用程序仍然可以运行,但页面顶部出现警告错误消息。定位器:span class=message message-error

整个框架是用Java实现的,Selenium Webdriver和Page Object/Page Factory模式。

我正在寻找一种可靠的解决方案来验证页面在以下情况下没有任何错误:

导航到相应的页面,当新页面初始化时,检查页面是否有错误(我需要检查两种情况) 我在页面上执行某些操作,搜索,单击某些内容,然后验证错误没有出现在页面上。不是他们。 我的校验错误方法:

public void checkError() {
    if(errorPage.size() > 0) {
        try {
            throw new TestException("Unexpected error appears: " + errorPage.get(0).getText());
        } catch (TestException e) {
            e.printStackTrace();
        }
    }
}

(其中一种)我的等待方法:

public void waitForPageLoaded() {

    if (driver.findElements(By.className("errorPage")).size() > 0) {

        try {
            throw new UnexpectedException("Unexpected error:" + driver.findElement(By.id("errorTrace")).getText());
        } catch (UnexpectedException e) {
            e.printStackTrace();
        }
    } else {
        ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver driver) {
                return ((JavascriptExecutor) driver).executeScript("return document.readyState").toString()
                        .equalsIgnoreCase("complete");
            }
        };
        WebDriverWait wait = new WebDriverWait(driver, 30);
        wait.until(expectation);
    }

}

使用 isDisplayed 方法的简单 if else 语句不起作用,因为当错误未出现在页面上时,我得到了 NoSuchElementException。

上面的方法可以在不同的情况下使用,但我想以一种通用的方式将所有内容收集在一个解决方案中。 DRY 解决方案是我的想法。

有什么建议吗?谢谢。

【问题讨论】:

  • 驱动程序已经默认等待就绪状态,所以在你的脚本中等待它是没有用的。而不是在通用服务员中隐藏通用错误断言,您应该在测试中明确断言错误,并使用肯定和否定的情况。
  • 你能给我举个例子吗?完全理解你在说什么,但我并不清楚用两种不同的输出处理正负情况。
  • @FlorentB。 Selenium 仅在 driver.get()... 上等待就绪状态,而不是在点击或任何其他用户触发的导航上。我不确定.back() 之类的。
  • @JeffC,规范说,当单击导致导航或调用Back/Forward/Refresh 时,驱动程序必须等待完成状态。我很确定 Chrome 就是这种情况,尽管上次我检查 geckodriver 在检测新页面时仍然存在问题,尤其是当导航是从复合操作触发时。我知道的唯一情况是,如果导航是通过SendKeys 触发的,驱动程序不会等待。除此之外,现在大部分内容都是通过 Ajax 更新的,这对页面的状态没有影响。
  • @FlorentB。那么规范所说的与实际发生的事情是两件不同的事情。我有很多次单击链接并从页面上拉出一些文本,却发现该页面尚未更改,因此我从旧页面上获取了文本。这就是为什么我使用我在回答中描述的方法使页面对象构造函数等待预期元素的原因。有关详细信息,请阅读this

标签: java selenium selenium-webdriver


【解决方案1】:

这里有几个选项。我将通过一个基本案例并解释一些其他可能的方法,希望您可以使用此代码并根据自己的喜好对其进行调整。

基本上,我的每个页面对象都确定它是否在构造函数中加载。我有一个使用waitForLocator 等待指定元素的等待。如果您的页面加载速度较慢,请在该区域中选择一个元素作为您的定位器。如果您有一些加载缓慢的区域,您可以重写它以非常轻松地等待元素列表,以确保页面的所有部分都已加载。

之后,您实现一个检查错误的方法和另一个检查警告的方法。你可以变得更漂亮,让他们返回错误/警告,这样你就可以将它们用于阳性测试等。

下面的页面对象非常基本。我正在做这个的愚蠢版本,如果有错误或警告,它只会抛出异常。如果您不希望测试因错误/警告而失败,例如,您绝对可以从构造函数等中取出这些检查。您故意触发它们,然后验证它们是否存在。

使用这种方法,您无需等到错误消息出现。您等待 waitForLocator 指示您的页面已完成加载...此时,您可以检查错误/警告而无需等待。

这就是我实现所有页面对象的方式。我在构造函数中放置了等待,然后只需要在我触发页面上的某些事件时添加等待,例如模态对话框启动。当触发事件时,触发该事件的方法会等待页面动态部分中的元素可见,例如等待对话框的容器元素可见。

public class PageObject
{
    private WebDriver driver;
    private By waitForLocator = By.id("someId"); // this is a locator for some element on the page that is last to load

    private By errorLocator = By.cssSelector("div.errorPage");
    private By warningLocator = By.cssSelector("span.message.message-error");
    private By buttonLocator = By.cssSelector("button");

    public PageObject(WebDriver webDriver)
    {
        this.driver = webDriver;

        // wait for page to finish loading
        new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(waitForLocator));

        if (errorExists())
        {
            throw new IllegalStateException("There are errors on the page.");
        }
        if (warningExists())
        {
            throw new IllegalStateException("There are warnings on the page.");
        }
    }

    public void clickButton()
    {
        driver.findElement(buttonLocator).click();
    }

    public boolean errorExists()
    {
        return !driver.findElements(errorLocator).isEmpty();
    }

    public boolean warningExists()
    {
        return !driver.findElements(warningLocator).isEmpty();
    }
}

您的脚本将如下所示。我正在使用 TestNG 断言来验证不存在错误/警告。

PageObject page = new PageObject(driver);
page.clickButton(); // do something that might trigger an error or warning
Assert.assertFalse(page.errorExists(), "Verify no errors exist");
Assert.assertFalse(page.warningExists(), "Verify no warnings exist");

【讨论】:

  • 谢谢杰夫,这是非常全面的答案。我尝试使用这个想法,并会让你知道结果!
  • 效果很好,感谢您的帮助!但是我遇到了另一个问题,我的 cucumber-jvm 钩子无法处理多个测试,因为在第一次测试之后,钩子关闭了我的驱动程序并且我得到了 session Id is null 错误。然而这是另一个问题,另一个问题:)
猜你喜欢
  • 2013-07-10
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 2012-03-14
  • 2019-04-15
  • 2019-11-16
  • 2016-03-08
相关资源
最近更新 更多