元素不可见异常 - 即使使用不同的 Selenium 等待
Element not visible exception - even if different Selenium waits are used
我正在尝试使用 Selenium 和 Java 自动执行 Web 应用程序的功能测试。在我的应用程序中有几个菜单。单击特定菜单时,会出现子菜单的下拉菜单
click to view screenshot of menu
我使用下面的代码点击子菜单
driver.findElement(By.xpath("id=menu")).click();
driver.findElement(By.xpath("id=sub_menu_a")).click();
但问题是它在第二行抛出一个 'ElementNotVisibleException'。即使我使用隐式 wait
也会发生同样的情况
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
显式等待
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
和流利的等待。
Wait<WebDriver> fluentWait=new FluentWait<WebDriver>(driver)
.withTimeout(60, TimeUnit.SECONDS)
.pollingEvery(2, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class,ElementNotVisibleException.class);
WebElement element=fluentWait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver){
driver.findElement(By.xpath("id=menu"));
return driver.findElement(By.xpath("id=sub_menu_a"));
}
});
element.click();
但运气不好。但是如果使用
添加睡眠时间,代码工作正常
Thread.sleep(sleeptime);
第一行代码前后。但这不是永久性的解决方案,因为页面加载时间可能会因网络速度和页面中的数据而异。还有其他解决办法吗?
流畅的等待应该可以正常工作。
尝试使用这样的东西:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
但我会选择 css 选择器,它们非常适合 html 页。
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#sub_menu_a")));
或者,如果您的 sub_menu_a 是 menu 的子项,我会选择
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#menu #sub_menu_a")));
你能试试吗
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("id=sub_menu_a")));
另外,如果您能提供 html 以找到正确的 xpath 会更好,因为我认为更好的 XPATH 将产生单击子菜单的结果。
很久以前我遇到过类似的问题(不记得确切的情况所以确实你的 HTML 页面被截断会有帮助)所以我被迫使用 Thread.sleep()
为了避免长时间等待,将提出类似这样的方法:
static void waitAndClick(WebDriver driver, By by, int attempts, int sleep) throws InterruptedException {
for (int i = 0; i < attempts; i++) {
WebElement element = null;
try {
element = driver.findElement(by);
} catch (NoSuchElementException e) {
// Do nothing
}
if (element == null) {
int time = sleep * (i + 1);
Thread.sleep(time);
} else {
element.click();
break;
}
}
throw new NoSuchElementException("Error");
}
这不是 100% 完整的解决方案,只是一个想法。
尝试使用 Actions class 看看它是否有效...
driver.findElement(By.xpath("id=menu")).click();
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
Actions myaction = new Actions(driver);
myaction.moveToElement(subMenu);
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(subMenu));
myaction.click().perform();
试试这个
WebElement menu=driver.findElement(By.xpath("id=menu"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", menu);
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
executor.executeScript("arguments[0].click();", subMenu);
希望这项工作
我正在尝试使用 Selenium 和 Java 自动执行 Web 应用程序的功能测试。在我的应用程序中有几个菜单。单击特定菜单时,会出现子菜单的下拉菜单 click to view screenshot of menu
我使用下面的代码点击子菜单
driver.findElement(By.xpath("id=menu")).click();
driver.findElement(By.xpath("id=sub_menu_a")).click();
但问题是它在第二行抛出一个 'ElementNotVisibleException'。即使我使用隐式 wait
也会发生同样的情况driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
显式等待
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
和流利的等待。
Wait<WebDriver> fluentWait=new FluentWait<WebDriver>(driver)
.withTimeout(60, TimeUnit.SECONDS)
.pollingEvery(2, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class,ElementNotVisibleException.class);
WebElement element=fluentWait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver){
driver.findElement(By.xpath("id=menu"));
return driver.findElement(By.xpath("id=sub_menu_a"));
}
});
element.click();
但运气不好。但是如果使用
添加睡眠时间,代码工作正常Thread.sleep(sleeptime);
第一行代码前后。但这不是永久性的解决方案,因为页面加载时间可能会因网络速度和页面中的数据而异。还有其他解决办法吗?
流畅的等待应该可以正常工作。 尝试使用这样的东西:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
但我会选择 css 选择器,它们非常适合 html 页。
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#sub_menu_a")));
或者,如果您的 sub_menu_a 是 menu 的子项,我会选择
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#menu #sub_menu_a")));
你能试试吗
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("id=sub_menu_a")));
另外,如果您能提供 html 以找到正确的 xpath 会更好,因为我认为更好的 XPATH 将产生单击子菜单的结果。
很久以前我遇到过类似的问题(不记得确切的情况所以确实你的 HTML 页面被截断会有帮助)所以我被迫使用 Thread.sleep() 为了避免长时间等待,将提出类似这样的方法:
static void waitAndClick(WebDriver driver, By by, int attempts, int sleep) throws InterruptedException {
for (int i = 0; i < attempts; i++) {
WebElement element = null;
try {
element = driver.findElement(by);
} catch (NoSuchElementException e) {
// Do nothing
}
if (element == null) {
int time = sleep * (i + 1);
Thread.sleep(time);
} else {
element.click();
break;
}
}
throw new NoSuchElementException("Error");
}
这不是 100% 完整的解决方案,只是一个想法。
尝试使用 Actions class 看看它是否有效...
driver.findElement(By.xpath("id=menu")).click();
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
Actions myaction = new Actions(driver);
myaction.moveToElement(subMenu);
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(subMenu));
myaction.click().perform();
试试这个
WebElement menu=driver.findElement(By.xpath("id=menu"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", menu);
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
executor.executeScript("arguments[0].click();", subMenu);
希望这项工作