Ответ 1
Вы также можете сделать:
driver.findElements( By.id("...") ).size() != 0
Что сохраняет неприятный try/catch
Как проверить, существует ли элемент с веб-драйвером?
Является ли использование try catch действительно единственным возможным способом?
boolean present;
try {
driver.findElement(By.id("logoutLink"));
present = true;
} catch (NoSuchElementException e) {
present = false;
}
Вы также можете сделать:
driver.findElements( By.id("...") ).size() != 0
Что сохраняет неприятный try/catch
Я согласен с ответом Майка, но там неявное 3-секундное ожидание, если не найдены никакие элементы, которые могут быть включены/выключены, что полезно, если вы много выполняете это действие:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
boolean exists = driver.findElements( By.id("...") ).size() != 0
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
Включение этого метода полезности должно повысить производительность, если вы выполняете множество тестов
Как говорится в комментарии, это на С#, а не на Java, но идея такая же. Я исследовал эту проблему широко, и в конечном итоге проблема заключается в том, что FindElement всегда возвращает исключение, когда элемент не существует. Существует не перегруженный вариант, который позволяет вам получить нуль или что-то еще. Вот почему я предпочитаю это решение над другими.
На самом деле это очень просто и элегантно после создания метода. Используя FindElementSafe вместо FindElement, я не вижу "уродливый блок try/catch", и я могу использовать простой метод Существует. Это будет выглядеть примерно так:
IWebElement myLink = driver.FindElementSafe(By.Id("myId"));
if (myLink.Exists)
{
myLink.Click();
}
Вот как вы расширяете IWebElement и IWebDriver
IWebDriver.FindElementSafe
/// <summary>
/// Same as FindElement only returns null when not found instead of an exception.
/// </summary>
/// <param name="driver">current browser instance</param>
/// <param name="by">The search string for finding element</param>
/// <returns>Returns element or null if not found</returns>
public static IWebElement FindElementSafe(this IWebDriver driver, By by)
{
try
{
return driver.FindElement(by);
}
catch (NoSuchElementException)
{
return null;
}
}
IWebElement.Exists
/// <summary>
/// Requires finding element by FindElementSafe(By).
/// Returns T/F depending on if element is defined or null.
/// </summary>
/// <param name="element">Current element</param>
/// <returns>Returns T/F depending on if element is defined or null.</returns>
public static bool Exists(this IWebElement element)
{
if (element == null)
{ return false; }
return true;
}
Вы можете использовать полиморфизм для изменения экземпляра класса IWebDriver класса FindElement, но это плохая идея с точки зрения обслуживания.
вы можете сделать утверждение.
см. пример
driver.asserts().assertElementFound("Page was not loaded",
By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);
вы можете использовать это, это является родным:
public static void waitForElementToAppear(Driver driver, By selector, long timeOutInSeconds, String timeOutMessage) {
try {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
} catch (TimeoutException e) {
throw new IllegalStateException(timeOutMessage);
}
}
Это работает для меня каждый раз:
if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
//THEN CLICK ON THE SUBMIT BUTTON
}else{
//DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
}
Я расширил реализацию Selenium WebDriver, в моем случае HtmlUnitDriver выставляет метод
public boolean isElementPresent(By by){}
вот так:
Вот мой код:
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
public class CustomHtmlUnitDriver extends HtmlUnitDriver {
public static final long DEFAULT_TIMEOUT_SECONDS = 30;
private long timeout = DEFAULT_TIMEOUT_SECONDS;
public long getTimeout() {
return timeout;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public boolean isElementPresent(By by) {
boolean isPresent = true;
waitForLoad();
//search for elements and check if list is empty
if (this.findElements(by).isEmpty()) {
isPresent = false;
}
//rise back implicitly wait time
this.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
return isPresent;
}
public void waitForLoad() {
ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver wd) {
//this will tel if page is loaded
return "complete".equals(((JavascriptExecutor) wd).executeScript("return document.readyState"));
}
};
WebDriverWait wait = new WebDriverWait(this, timeout);
//wait for page complete
wait.until(pageLoadCondition);
//lower implicitly wait time
this.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
}
}
Использование:
CustomHtmlUnitDriver wd = new CustomHtmlUnitDriver();
wd.get("http://example.org");
if (wd.isElementPresent(By.id("Accept"))) {
wd.findElement(By.id("Accept")).click();
}
else {
System.out.println("Accept button not found on page");
}
Напишите следующий метод с использованием Java:
protected boolean isElementPresent(By by){
try{
driver.findElement(by);
return true;
}
catch(NoSuchElementException e){
return false;
}
}
Вызовите вышеуказанный метод во время утверждения.
String link = driver.findElement(By.linkText(linkText)).getAttribute("href")
Это даст вам ссылку, на которую указывает элемент.
С версией 2.21.0 selenium-java.jar вы можете это сделать;
driver.findElement(By.id("...")).isDisplayed()
Как я понимаю, это стандартный способ использования веб-драйвера.