私はJavaでSelenium3.4を使用しています。 Chromeでは、すべてが正常に機能します。しかし、Firefoxを使用する必要があり、何かが壊れています。
Dojo UIのテストを自動化しているので、DojoUIが多くのレンダリングを行うまで待つ必要があります。これが私がやっていることです。Chromeでも問題なく動作します。通常、私のコードでは20秒の暗黙的な待機が設定されていることに注意してください。
_driver.switchTo().defaultContent();
driver.switchTo().frame(driver.findElement(By.id("contentframe"))); // relying on implicit wait
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
(new WebDriverWait(driver, 120)).
until(ExpectedConditions.elementToBeClickable(By.id("some_id")));
_
コードを簡略化したので、暗黙の待機が20秒に戻される方法がわかりません。問題が発生しても、とにかくそこには到達しません。 WebDriverWaitは例外を引き起こします。例外は_TypeError: can't access dead object
_と言います
待機内から対応するメッセージがあります。
_May 16, 2017 3:36:11 PM org.openqa.Selenium.support.ui.ExpectedConditions findElement
WARNING: WebDriverException thrown by findElement(By.id:
some_id)
org.openqa.Selenium.WebDriverException: TypeError: can't access dead object
_
どうやら、geckodriverによるJavaScriptエラー出力もあります。
_JavaScript error: chrome://marionette/content/listener.js, line 1555: TypeError: can't access dead object
*************************
A coding exception was thrown and uncaught in a Task.
Full message: TypeError: can't access dead object
Full stack: find_@chrome://marionette/content/element.js:284:7
element.find/</findElements<@chrome://marionette/content/element.js:255:15
implicitlyWaitFor/</elementSearch@chrome://marionette/content/element.js:600:15
implicitlyWaitFor/<@chrome://marionette/content/element.js:627:5
implicitlyWaitFor@chrome://marionette/content/element.js:593:10
element.find/<@chrome://marionette/content/element.js:254:24
element.find@chrome://marionette/content/element.js:253:10
findElementsContent@chrome://marionette/content/listener.js:1314:19
TaskImpl_run@resource://gre/modules/Task.jsm:319:42
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
TaskImpl_handleResultValue@resource://gre/modules/Task.jsm:389:16
TaskImpl_run@resource://gre/modules/Task.jsm:327:15
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
dispatch/<@chrome://marionette/content/listener.js:186:15
*************************
*************************
A coding exception was thrown and uncaught in a Task.
Full message: TypeError: can't access dead object
Full stack: find_@chrome://marionette/content/element.js:284:7
element.find/</findElements<@chrome://marionette/content/element.js:255:15
implicitlyWaitFor/</elementSearch@chrome://marionette/content/element.js:600:15
implicitlyWaitFor/<@chrome://marionette/content/element.js:627:5
implicitlyWaitFor@chrome://marionette/content/element.js:593:10
element.find/<@chrome://marionette/content/element.js:254:24
element.find@chrome://marionette/content/element.js:253:10
findElementsContent@chrome://marionette/content/listener.js:1314:19
TaskImpl_run@resource://gre/modules/Task.jsm:319:42
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
TaskImpl_handleResultValue@resource://gre/modules/Task.jsm:389:16
TaskImpl_run@resource://gre/modules/Task.jsm:327:15
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
dispatch/<@chrome://marionette/content/listener.js:186:15
_
さらに、私の自動例外処理はスクリーンショットを撮ろうとしますが、それはまったく同じエラーで失敗します。コード行は次のとおりです。
File snapshotTempFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
そして今回のgeckodriverからの出力は次のとおりです。
_A coding exception was thrown and uncaught in a Task.
Full message: TypeError: can't access dead object
Full stack: capture.viewport@chrome://marionette/content/capture.js:65:7
takeScreenshot@chrome://marionette/content/listener.js:1782:14
dispatch/</req<@chrome://marionette/content/listener.js:188:22
TaskImpl_run@resource://gre/modules/Task.jsm:319:42
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
dispatch/<@chrome://marionette/content/listener.js:186:15
_
それで、これを正しく機能させるために何かできることはありますか?そして、これは私がgeckodriverのバグとして提起する必要があるものですか?
私がグーグルアウトできる唯一のものはこれです: https://github.com/mozilla/geckodriver/issues/614 そして唯一提案された解決策はdriver.switchTo().defaultContent()
です。これでスクリーンショットルーチンが修正される可能性がありますが、待機している要素がコンテンツフレーム内にあるため、この修正を待機に使用することはできません。
要素some_id
を待っている間に、フレームに新しい参照が再ロードされているようです。ドライバによって返されるエラーはWebDriver
プロトコルによって定義されていないため、この問題をバグとして分類します。
それを機能させるための最良のチャンスは、おそらくカスタムウェイターを実装してフレーム/要素を見つけ、未処理の例外をスキップすることです。
WebElement elem = waiter.Until(elementToBeClickableInFrame(By.id("contentframe"),
By.id("some_id")));
public static ExpectedCondition<WebElement> elementToBeClickableInFrame(final By locatorFrame, final By locator) {
return new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
try {
driver.switchTo().defaultContent();
driver.switchTo().frame(driver.findElement(locatorFrame));
WebElement elem = driver.findElement(locator);
return elem.isDisplayed() && elem.isEnabled() ? elem : null;
} catch (Exception e) {
return null;
}
}
@Override
public String toString() {
return "element located by: " + locator + " in " + locatorFrame;
}
};
}
これがあなたに役立つかどうかはわかりませんが、このエラーメッセージに遭遇したとき、私は次のことでそれを乗り越えることができました:
driver.switchTo().defaultContent();
driver.switchTo().frame(0);
iframe内の要素との各相互作用の間。
例:
driver.switchTo().frame(0);
myPage.selectElement(getCycleSummary());
driver.switchTo().defaultContent();
driver.switchTo().frame(0);
myPage.selectDisplayedElement(this.getCycleBtn());
ドライバスイッチがないと、デッドオブジェクトエラーが発生します。