Napisałem kilka przypadków testowych w Selenium WebDriver używając Java i wykonuję je na siatce (hub i wiele węzłów). Zauważyłem, że kilka przypadków testowych nie powiodło się z powodu NoSuchElementException
. Jaki jest najlepszy i niezawodny sposób, aby uniknąć NoSuchElementException
i upewnić się, że element jest zawsze znaleziony?Jaki jest najlepszy sposób na uniknięcie wyjątku NoSuchElementException w Selenie?
Odpowiedz
Nigdy nie można być pewnym, że element zostanie znaleziony, w rzeczywistości jest to celem testów funkcjonalnych - aby powiedzieć, czy coś zmieniło się na twojej stronie. Ale jedna rzecz, która zdecydowanie pomaga jest dodanie czeka na elementach, które są często powodując NoSuchElementException
jak
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));
można również wykorzystać FluentWait
,
Każda instancja FluentWait
określa maksymalną ilość czasu, aby czekać na warunek , a także częstotliwość, z jaką należy sprawdzać stan.
Ponadto użytkownik może skonfigurować oczekiwanie na ignorowanie określonych typów wyjątków podczas oczekiwania, takich jak NoSuchElementExceptions
podczas wyszukiwania elementu na stronie.
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
Jest to z pewnością pomocne. Ale czy możemy mieć ogólną metodę nakładania ... tj. Na przykład, która czeka na załadowanie strony całkowicie, następnie znajduje element i jeśli element nie zostanie znaleziony odświeża stronę i to trwa aż do upływu czasu fluentwait. –
możesz spróbować połączyć "wyraźne oczekiwanie otoczone przez próbę i złap" z płynnym oczekiwaniem .. – Amith
spróbuj {"używaj wyraźnego czekania"} catch (wyjątek e) {odśwież stronę i korzystaj płynnie} – Amith
Całkowicie zgadzam się Petr Menšík powyżej. Sprawa, której nigdy nie można powiedzieć, czy element jest obecny. Powinieneś jasno zrozumieć, dlaczego tak się dzieje. Z mojego doświadczenia mogę powiedzieć, że powinno to się dzieje z powodu następujących powodów:
- 1) Na stronie jest wciąż renderowane i już zakończył swoją elementu szukanie i uzyskać żadnego wyjątku elementu.
- 2) Drugim powodem jest to, AJAX nie powrócił jeszcze i masz już uzyskać
NoSuchElementException
- 3) trzeci jest najbardziej oczywiste: Element nie jest naprawdę na stronie kiedykolwiek.
Najbardziej niezawodny sposób, aby IMHO obsłużyć wszystkie te trzy warunki za pomocą jednego wywołania funkcji, to użyć fluentWait
zgodnie z sugestią Amith003.
więc kod jest następująca:
niech ur element ma lokalizatora:
String elLocXpath= "..blablabla";
WebElement myButton= fluentWait(By.xpath(elLocXpath));
myButton.click();
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(org.openqa.selenium.NoSuchElementException.class);
WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
}
);
return foo;
};
Także, jeśli twoim celem jest solidne kod okład fluentWait()
z try{} catch{}
bloku.
także nie zapomnieć o
public boolean isElementPresent(By selector)
{
return driver.findElements(selector).size()>0;
}
że jest również przydatna.
Podsumowując wszystkie powyższe, jeśli chcesz uniknąć wyjątku NoElement
, po prostu zrób to poprawnie, ponieważ nikt nie może zapewnić obecności elementu na stronie.
Mam nadzieję, że teraz jest dla ciebie bardziej przejrzyste.Pozdrowienia
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>));
elementToBeClickable czeka Włącz i Visible elementu
public WebElement fluientWaitforElement(WebElement element, int timoutSec, int pollingSec) {
FluentWait<WebDriver> fWait = new FluentWait<WebDriver>(driver).withTimeout(timoutSec, TimeUnit.SECONDS)
.pollingEvery(pollingSec, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class, TimeoutException.class);
for (int i = 0; i < 2; i++) {
try {
//fWait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//*[@id='reportmanager-wrapper']/div[1]/div[2]/ul/li/span[3]/i[@data-original--title='We are processing through trillions of data events, this insight may take more than 15 minutes to complete.']")));
fWait.until(ExpectedConditions.visibilityOf(element));
fWait.until(ExpectedConditions.elementToBeClickable(element));
}
catch (Exception e) {
System.out.println("Element Not found trying again - " + element.toString().substring(70));
e.printStackTrace();
}
}
return element;
}
Zwykle używam tej linii w funkcji main
public static void main(String[] args) throws ParseException {
driver= new ChromeDriver();
driver.manage().window().maximize();
**driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);**
nadzieję, że to pomaga.
Możemy zastosować poniżej kodów, aby usunąć ten warunek wyjątku
Stosując WebDriverWait, webdriver obiektu oczekiwania na określony czas (w sekundach) elementu do jego widoczności.
WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.visibilityOf(link));
Możemy obsłużyć NoSuchElementException przez blok try-catch wewnątrz metody Generic
public boolean isElementPresent(By by) { boolean isPresent = true; try { driver.findElement(by); } catch (NoSuchElementException e) { isPresent = false; } return isPresent }
http://selenium-code.blogspot.in/2017/08/selenium-exception-nosuchelementexcepti.html
Jest to z pewnością pomocne. Czy możemy mieć ogólne warunki oczekiwania, abyśmy nie musieli sprawdzać, który warunek ExpectedConditions ma być używany? –
Istnieje również dostęp do 'niejawnego' oczekiwania oferowanego przez 'API Webdriver'a' ale ponieważ po prostu ustawia on arbitralny okres 'nic nie rób', bardzo podobny do' snu', zachęca się do używania 'wyraźnego oczekiwania', jak wyżej dla niezawodności i szybkości. –
To jest rzeczywiście najczystszy i najprostszy kod jaki widziałem ze wszystkich próbek kodu. Dzięki! – mkorman