我是selenium webdriver的新手,我在IE 8上使用2.31版本,testng 6.8和防火测试。我正在写这个方案中的测试: 我有测试类,我有使用testng @Test注释的方法。它看起来像这样:
@Test(description="click Save Button ", dependsOnMethods = { "edit form" })
public void clickSaveButton(ITestContext context) {
page.clickSaveButton(driver);
}
然后,你可以看到我有一个页面类,我存储元素id,xpaths等。它像这样lokks:
public void clickSaveButton(WebDriver driver){
Configuration.clickfoundElement(By.id(conf.get("saveButton")), driver);
}
conf是表示属性文件的对象。 最后我有Configuration类,我在这里做了一些想法:
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发生是因为我找不到任何元素(因为最后的测试操作没有发生所以我仍然在上一个站点,没有这个元素)你能告诉我为什么会出现这种情况(重要的并不总是但有时只是)以及如何预防?
提前致谢。
答案 0 :(得分: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,您有几个选择:
我个人在我的所有测试代码中使用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找到它然后对它执行操作之间的ms。)
在上面的示例中,我通过在构造函数中初始化页面工厂而受到欺骗,您不必这样做,但我发现它通常是一种很好的简单方法。
有关页面工厂的更多信息,请查看Selenium Wiki。
答案 1 :(得分:1)
谢谢大家的时间。事实证明我的问题发生了,因为我在测试的应用程序中有类似popup winowow的东西(richFaces rich:modalPanel准确)。这导致DOM“落后”这个弹出窗口仍然可见,但是由于它而无法点击其中的元素。什么解决了我的问题只是等待更长一点的元素可以通过ExpectedConditions.elementToBeClickable(By by)点击,这确保我的弹出窗口在关闭它之后消失并且点击另一个元素是可能的。这使得Ardesco的答案最好。再次感谢你。
答案 2 :(得分:0)
您没有在while循环中递增尝试变量。
我不知道一个正确的方法,但我不会使用while循环来搜索元素。也许您应该尝试使用driver.findElements()
而不是driver.findElement()
并使用一些断言。例如,尝试检查按钮是否真的存在。
答案 3 :(得分: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类似的行为。确保您的webdriver中有正确的缩放设置,因为这似乎是click()未被正确触发的一个原因。有些人似乎已经通过点击几次解决了这个问题,这似乎是一个肮脏的解决方案。我的解决方案IE7,8&amp; 9 click()用来执行实际的onclick javascript函数
((JavaScriptExecutor)driver).executeScript("onclickFunction();");
这只是可以接受的,因为测试主断言不是应该调用javascript函数onclick而是测试javascript函数动态地向页面添加元素。
关于StaleElementReferenceException,我会在每个测试中实例化一个新的页面对象,这样你就不会得到过时的元素,而是从一个干净的状态开始。在JUnit4中,这将在你的@Before方法中。