テストを実行すると、次のエラーが発生します:org.openqa.selenium.StaleElementReferenceException:要素がDOMにアタッチされなくなりました
上記の例外を解決する方法について何かアイデアはありますか?これは、動的なrefXpath式を持つグリッドで発生します
この問題は、WebdriverWrapper および WebElementWrapper と呼ばれる方法で回避できます。
これらのラッパーが行うことは、内部で StaleElementException を処理し、ロケーターを使用して再評価し、新しい WebElement オブジェクトを取得することです。このようにして、例外を処理するコードをコードベース全体に広げ、それを 1 つのクラスにローカライズする必要があります。
これらのいくつかのクラスだけをオープンソース化することをすぐに検討し、興味がある場合はここにリンクを追加します.
この例外は、ページ上に存在しない WebElement のメソッドを使用しようとするとスローされます。グリッドがデータを動的にロードしているときにグリッドを更新すると、そのグリッド上の要素への参照はすべて「古く」なります。参照しようとしている要素がテストのページにあることを再確認してください。オブジェクトの再インスタンス化が必要になる場合があります。
この問題も発生しました。モーダル パネルの読み込みが競合状態に陥り、タイムアウトになるまで待機し続けることは明らかです。
私は何度も試しましたが、解決策は、webDriver によって正確に検出されるまでモーダル パネルの読み込みを保持し、同時に webDriver インスタンスを更新し続け、モーダル パネル内で WebElements を見つけようとすることであることがわかりました。
したがって、解決策は次のようになります。たとえば、 MyModalPanelが ModalPanel Id の場合、次のようにします。
page.openModalPanel();
Assert.assertTrue(page.waitTillDisplay( "MyModalPanelContentDiv"), Wait.MODAL_PANEL));
page.fillInFormInModalpanel(formObj);
また、waitTillDisplay コードは WebDriver の Web サイトにあります。参照用にコードをここに貼り付けます。
public Boolean waitTillDisplay(final String id, int waitSeconds){
WebDriverWait wait = new WebDriverWait(driver, waitSeconds);
Boolean displayed = wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return driver.findElement(By.id(id)).isDisplayed();
}
});
return displayed;
}
FluentWaitとExpectedCondition適用オーバーライドを使用しました: https ://gist.github.com/djangofan/5112655 。これは、他の人がこれに答える方法とは異なり、完成したブロック内の例外を処理し、連続した試行をそのブロックにラップできるようにします。これはもっとエレガントだと思います。
public static void clickByLocator( final By locator ) {
final long startTime = System.currentTimeMillis();
driver.manage().timeouts().implicitlyWait( 5, TimeUnit.SECONDS );
Wait<WebDriver> wait = new FluentWait<WebDriver>( driver )
.withTimeout(90000, TimeUnit.MILLISECONDS)
.pollingEvery(5500, TimeUnit.MILLISECONDS);
//.ignoring( StaleElementReferenceException.class );
wait.until( new ExpectedCondition<Boolean>() {
@Override
public Boolean apply( WebDriver webDriver ) {
try {
webDriver.findElement( locator ).click();
return true;
} catch ( StaleElementReferenceException e ) { // try again
return false;
}
}
} );
driver.manage().timeouts().implicitlyWait( DEFAULT_IMPLICIT_WAIT, TimeUnit.SECONDS );
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
log("Finished click after waiting for " + totalTime + " milliseconds.");
}
要素をクリックした後、要素のプロパティを取得しようとしている可能性があります。
私は同じ問題を抱えていました。ボタンをクリックした後、ボタンの getText() を試みていました。私の場合、ボタンをクリックすると、新しいウィンドウが表示されます。
より柔軟にするためにいくつかの変更を加えました。
delegate void StaleFunction(IWebElement elt);
private static void StaleElementHandleByID(By by, StaleFunction func )
{
int count = 0;
while (count < 4)
{
try
{
IWebElement yourSlipperyElement = Driver.FindElement(by);
func(yourSlipperyElement);
count = count + 4;
}
catch (StaleElementReferenceException e)
{
count = count + 1;
}
}
}
StaleElementHandleByID(By.Id("identDdl"),
delegate(IWebElement elt)
{
SelectElement select = new SelectElement(elt);
select.SelectByText(tosave.ItemEquipamentoCem.CodigoCne.ToString());
});
迅速で汚い解決策:
el.click()
time.sleep(1)
次に、反復的に解析を続けます
この場合、テストはまだロードされていない、または更新された要素を探しています。その結果、StaleElementException. 簡単な解決策は、fluentWait を追加することです。