使用Java+;验证页面错误消息的强健解决方案;Selenium Web驱动程序
情境:给定一个连接到外部系统的复杂webapp。如果外部系统关闭,可能有两个选项使用Java+;验证页面错误消息的强健解决方案;Selenium Web驱动程序,java,selenium,selenium-webdriver,Java,Selenium,Selenium Webdriver,情境:给定一个连接到外部系统的复杂webapp。如果外部系统关闭,可能有两个选项 案例:出现div中的大胖stacktrace。定位器div类:errorPage 案例:应用程序仍然工作,但页面顶部会出现警告错误消息。定位器:span class=消息错误 整个框架是用Java、SeleniumWebDriver和页面对象/页面工厂模式实现的 我正在寻找一个健壮的解决方案,以验证页面在以下情况下没有任何错误: 导航到适当的页面,当新页面初始化时,检查页面上是否有任何错误(我需要检查两种情况) 我
errorPage
span class=消息错误
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);
}
}
public void waitForPageLoaded(){
if(driver.findElements(By.className(“errorPage”)).size()>0){
试一试{
抛出新的意外异常(“意外错误:+driver.findElement(By.id(“errorTrace”)).getText());
}捕获(意外异常e){
e、 printStackTrace();
}
}否则{
ExpectedCondition expectation=新的ExpectedCondition(){
公共布尔应用(WebDriver驱动程序){
return((JavascriptExecutor)driver.executeScript(“return document.readyState”).toString()
.equalsIgnoreCase(“完成”);
}
};
WebDriverWait wait=新的WebDriverWait(驱动程序,30);
等待,直到(期望);
}
}
带有isDisplayed方法的简单if-else语句不起作用,因为当错误没有出现在页面上时,我没有得到任何TouchElementException
上面的方法可以在不同的情况下使用,但我希望以一种通用的方式将所有内容收集到一个解决方案中。干法是我的主意
有什么建议吗?谢谢。您在这里有几个选择。我将介绍一个基本的案例,并解释一些其他可能的方法,希望您可以使用此代码并根据自己的喜好进行调整 基本上,我的每个页面对象都决定是否在构造函数中加载它。我使用
waitForLocator
等待指定的元素。如果页面的加载速度较慢,请选择该区域中的一个元素作为定位器。如果您有一些加载缓慢的区域,您可以重写它以等待元素列表,以确保页面的所有部分都已加载
然后,实现一个检查错误的方法和另一个检查警告的方法。您可以让fancier让他们返回错误/警告,以便您可以将其用于阳性测试等
下面的页面对象非常基本。我正在做一个愚蠢的版本,如果有错误或警告,就会抛出一个异常。如果你不希望你的测试在错误/警告时失败,例如,你故意触发它们,然后验证它们是否存在,那么你完全可以从构造函数中取出这些检查
使用这种方法,您无需等待错误消息出现。您等待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");
默认情况下,驱动程序已经在等待就绪状态,因此在脚本中等待它是无用的。你应该在测试中用正反两种情况明确地断言错误,而不是在一个普通的服务生中隐藏一个普通的错误断言。你能给我一个例子吗?“我完全理解你们的意思,但我不清楚如何处理两种不同输出的正负情况”。@FlorentB。Selenium只等待
驱动程序上的就绪状态。get()
。。。不是在点击或任何其他用户触发的导航。我不确定.back()
等等。@JeffC,规范中说,当单击导致导航或调用后退/前进/刷新时,驱动程序必须等待完成状态。我很确定Chrome就是这种情况,尽管上次我检查geckodriver时在检测新页面时仍然存在问题,特别是当导航是由复合动作触发时。我所知道的唯一情况是,如果通过SendKeys
触发导航,驾驶员不会等待。除此之外,现在大部分内容都是通过Ajax更新的,这对页面的状态没有影响。@FlorentB。规范所说的和实际发生的是两件不同的事情。我有很多次点击一个链接并从页面中提取一些文本,结果发现页面还没有更改,所以我从旧页面中提取了文本。这就是为什么我使用我在回答中描述的方法,使页面对象构造函数等待预期的元素。关于一些细节,请阅读。谢谢杰夫,这是一个非常全面的答案。我尝试使用这个想法,并会让你知道结果!它工作得很好,谢谢你的帮助!然而,我面临另一个问题,我的cucumber jvm钩子无法处理多个测试,因为在第一次测试之后,钩子关闭了我的驱动程序,我得到的会话Id为null错误。然而,这是另一个问题,另一个问题:)