0

我是 selenium webdriver 的新手,我正在使用 2.31 版本、testng 6.8 和 IE 8 上的防火测试。我正在这个方案中编写我的测试:我有测试类,其中我有带有 testng @Test 注释的方法。它看起来像这样:

@Test(description="click Save Button ", dependsOnMethods = { "edit form" })
public void clickSaveButton(ITestContext context) {
    page.clickSaveButton(driver);

}

然后,如您所见,我有一个页面类,我在其中存储元素 id、xpath 等。它像这样:

public void clickSaveButton(WebDriver driver){
    Configuration.clickfoundElement(By.id(conf.get("saveButton")), driver);
}

conf 是表示属性文件的对象。最后我有配置类,我会这样想:

public static void clickfoundElement(By by, WebDriver driver){
    int attempts = 0;

    while(attempts < 10) {
        try {

            driver.findElement(by).click();
            break;
        } catch(NoSuchElementException e) {
            System.out.println("NoSuchElementException");
            Reporter.log("NoSuchElementException<br/>");
            if(attempts==9){
                throw(e);

            }
        }
        catch(StaleElementReferenceException e) {
            System.out.println("StaleElementReferenceException");
            Reporter.log("StaleElementReferenceException<br/>");
            if(attempts==9){
                throw(e);
            }
        }}

这使我无法拥有 NoSuchElementException 和 StaleElementReferenceException 并且工作得很好。

我的第一个问题是这种方法是否正确?第二个也是最重要的问题是,我有时会遇到以下问题:

Testng 说“clickSaveButton”(在最终报告中)已通过,但实际上 clickSaveButton 操作没有发生(我可以看到它在测试期间看着我的浏览器)。在下一个测试的最后,我有“NoSuchElementException”(特别是当下一个测试不是点击某些东西而只是从 html 组件获取文本时)。当然这个 NoSuchElementException 发生是因为我真的没有要寻找的元素(因为最后一个测试操作没有发生所以我仍然在上一个站点,没有这个元素)你能告诉我为什么会发生这种情况(重要的并不总是但只是有时)以及如何预防?

提前致谢。

4

4 回答 4

1

我建议您使用显式等待来等待元素可见。这是通过 WebDriverWait 完成的,这将更改您的代码:

public void clickSaveButton(WebDriver driver){
    Configuration.clickfoundElement(By.id(conf.get("saveButton")), driver);
}

对此:

public void clickSaveButton(WebDriver driver) {
    WebDriverWait doWait = new WebDriverWait(driver, 15 , 100);
    WebElement elementToClick = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(conf.get("saveButton"))));
    elementToClick.click();
}

它还完全摆脱了您的 clickfoundElement() 方法。这不会阻止 StaleElementExceptions 的发生。StaleElementException 是由正在修改的 DOM 以及要与之交互的元素被销毁然后重新创建引起的。

为了避免 StaleElementExceptions 你有几个选择:

  1. 每次使用时始终使用定位器找到元素。
  2. 在支持中使用 PageFactory 类。

我个人在所有测试代码中都使用 PageFactories,一个基本示例如下所示:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;

public class LoginExample {

  @FindBy(how = How.ID, using = "username")
  private WebElement usernameField;
  @FindBy(how = How.ID, using = "password")
  private WebElement passwordField;
  @FindBy(how = How.ID, using = "login")
  private WebElement submitButton;

  public LoginExample(WebDriver driver) {
    PageFactory.initElements(driver, this);
  }

  public void enterCredentialsAndSubmitForm(String username, String password) {
    usernameField.clear();
    usernameField.sendKeys(username);
    passwordField.clear();
    passwordField.sendKeys(password);
    submitButton.click();
  }
}

@FindBy 注解有效地创建了一个代理 WebElement,每次使用此 WebElement 时,注解中指定的定位器将用于再次找到它,因此不会再出现 StaleElementException 错误(除非您很不幸,元素在几毫秒之间发生了变化Selenium 找到它,然后对其执行操作)。

在上面的示例中,我通过在构造函数中初始化页面工厂有点作弊,您不必这样做,但我发现它通常是一种很好且简单的方法。

有关页面工厂的更多信息,请查看Selenium Wiki

于 2013-03-15T09:08:47.727 回答
1

谢谢大家的时间。事实证明,我的问题出现了,因为我正在测试的应用程序中有类似弹出窗口的东西(确切地说是richFaces rich:modalPanel)。这导致该弹出窗口“后面”的 DOM 仍然可见,但无法单击其中的元素。解决我的问题的方法是稍等片刻,让元素可以通过 ExpectedConditions.elementToBeClickable(By by) 进行点击,这确保了我的弹出窗口在关闭它并单击另一个元素后消失了。这使得 Ardesco 做出了最好的回答。多谢一次。

于 2013-03-22T08:58:22.093 回答
0

您没有在 while 循环中增加尝试变量。我不知道正确的方法,但我不会使用 while 循环来搜索元素。也许您应该尝试使用driver.findElements()而不是driver.findElement()使用一些断言。例如,尝试检查按钮是否真的存在。

于 2013-03-15T07:59:07.877 回答
0

我可能会通过创建一个 By 变量来解决这个问题,然后将该变量传递给页面对象中的以下方法,如下所示:

By saveButton = By.id("saveButton");

public By getSaveButton() {
  waitForElementPresent(saveButton, 15);
  return driver.findElement(saveButton);
}

public void waitForElementPresent(final By locator, int timeout) {
  ExpectedCondition e = new ExpectedCondition<Boolean>() {
    public Boolean apply(WebDriver driver) {
      return driver.findElements(locator).size() > 0;
    }
  };

  WebDriverWait wait = new WebDriverWait(driver, timeout);
  wait.until(e);

}

可以将预期条件更改为所需条件。然后在您的测试中,单击保存按钮:

page.getSaveButton().click();

至于在 IE8 上没有发生 click(),我在 RemoteWebDriver 上看到过类似的行为。确保您的网络驱动程序中有正确的缩放设置,因为这似乎是 click() 未正确触发的原因之一。有些人似乎已经通过点击几次来解决这个问题,这似乎是一个肮脏的解决方案。我对 IE7,8 & 9 click() 的解决方案是执行实际的 onclick javascript 函数 ((JavaScriptExecutor)driver).executeScript("onclickFunction();");

这只是可接受的,因为测试的主要断言不是应该调用 javascript 函数 onclick 而是测试 javascript 函数是否动态地将元素添加到页面。

关于 StaleElementReferenceException,我会在每个测试中实例化一个新的页面对象,这样你就不会得到陈旧的元素,并且你从一个干净的状态开始。在 JUnit4 中,这将在您的 @Before 方法中。

于 2013-03-20T13:37:19.737 回答