web-dev-qa-db-ja.com

geckodriverの「デッドオブジェクトにアクセスできません」

私は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()です。これでスクリーンショットルーチンが修正される可能性がありますが、待機している要素がコンテンツフレーム内にあるため、この修正を待機に使用することはできません。

8

要素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;
    }
  };
}
2
Florent B.

これがあなたに役立つかどうかはわかりませんが、このエラーメッセージに遭遇したとき、私は次のことでそれを乗り越えることができました:

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());

ドライバスイッチがないと、デッドオブジェクトエラーが発生します。

3
jwest