【问题标题】:Test passed but action did not happen selenium webdriver + testng测试通过但没有采取行动 selenium webdriver + testng
【发布时间】:2013-03-14 10:27:17
【问题描述】:

我是 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 发生是因为我真的没有要寻找的元素(因为最后一个测试操作没有发生所以我仍然在上一个站点,没有这个元素)你能告诉我为什么会发生这种情况(重要的并不总是但只是有时)以及如何预防?

提前致谢。

【问题讨论】:

    标签: java selenium webdriver testng


    【解决方案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

    【讨论】:

    • 感谢您的回答。我不同意我的 clickFoundElement() 方法不能帮助我避免 StaleElementException。那是因为我试图从一开始就找到每个循环迭代,所以在每次迭代中 driver.findElement(by) 都是新元素。最终,大多数情况下,经过一两次迭代后,DOM 最终是最新的,并且不会发生异常。我会阅读更多关于 PageFactories 的内容,谢谢。
    • 我没有说您的 clickFoundElement() 不会帮助您避免 StaleElementExceptions。我说过使用显式等待不会帮助您避免 StaleElementExceptions,这就是为什么我进入关于 Java 页面工厂的答案的第二部分。显式等待完成了一半的工作,而 Java 页面工厂完成了另一半。使用显式等待是执行 clickFoundElement() 方法前半部分的正确方法。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 感谢您的回答。当然,我的循环中有尝试变量的增量,它只是没有粘贴,对此感到抱歉。不知道司机怎么样。 findElements() 将帮助我解决“测试通过但未采取行动”的问题。我想补充一点,我的测试大部分工作正常,但有时我会遇到这样的情况。这可能不是找不到元素的问题,因为正如我所说的测试通过了。
      【解决方案4】:

      我可能会通过创建一个 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 方法中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-17
        • 2015-09-22
        • 2016-04-25
        • 1970-01-01
        • 2021-04-18
        • 1970-01-01
        • 2014-09-01
        • 1970-01-01
        相关资源
        最近更新 更多