Ja, wenn Sie Probleme mit StaleElementReferenceExceptions haben, liegt dies daran, dass Ihre Tests schlecht geschrieben sind. Es ist eine Rennbedingung. Stellen Sie sich das folgende Szenario vor:
WebElement element = driver.findElement(By.id("foo"));
// DOM changes - page is refreshed, or element is removed and re-added
element.click();
An dem Punkt, an dem Sie auf das Element klicken, ist die Elementreferenz nicht mehr gültig. Für WebDriver ist es nahezu unmöglich, alle Fälle zu erraten, in denen dies passieren könnte. Daher wirft es die Hände hoch und gibt Ihnen die Kontrolle, wer als Test- / App-Autor genau wissen sollte, was passieren kann oder nicht. Sie möchten explizit warten, bis sich das DOM in einem Zustand befindet, in dem Sie wissen, dass sich nichts ändert. Verwenden Sie beispielsweise ein WebDriverWait, um auf das Vorhandensein eines bestimmten Elements zu warten:
// times out after 5 seconds
WebDriverWait wait = new WebDriverWait(driver, 5);
// while the following loop runs, the DOM changes -
// page is refreshed, or element is removed and re-added
wait.until(presenceOfElementLocated(By.id("container-element")));
// now we're good - let's click the element
driver.findElement(By.id("foo")).click();
Die PresenceOfElementLocated () -Methode würde ungefähr so aussehen:
private static Function<WebDriver,WebElement> presenceOfElementLocated(final By locator) {
return new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
};
}
Sie haben völlig Recht damit, dass der aktuelle Chrome-Treiber ziemlich instabil ist, und Sie werden erfreut sein zu hören, dass der Selenium-Trunk über einen neu geschriebenen Chrome-Treiber verfügt, bei dem der größte Teil der Implementierung von den Chromium-Entwicklern als Teil ihres Baums durchgeführt wurde.
PS. Anstatt explizit wie im obigen Beispiel zu warten, können Sie auch implizite Wartezeiten aktivieren. Auf diese Weise wird WebDriver immer bis zum angegebenen Zeitlimit wiederholt, bis das Element vorhanden ist:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)
Nach meiner Erfahrung ist explizites Warten jedoch immer zuverlässiger.