Не удается получить доступ к мертвому объекту в geckodriver

Я использую Selenium 3.4 с Java. С Хромом все работает нормально. Но мне нужно использовать Firefox, а там что-то ломается.

Я автоматизирую тестирование пользовательского интерфейса Dojo, и мне нужно подождать, пока пользовательский интерфейс Dojo выполнит большую часть рендеринга. Итак, вот что я делаю, и это прекрасно работает в 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

Также есть некоторые ошибки JavaScript, по-видимому, от geckodriver:

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

Итак, могу ли я что-нибудь сделать, чтобы это работало правильно? И это то, что мне нужно поднять как ошибку геккодрайвера?

Единственное, что я смог найти в Google, это: https://github.com/mozilla/geckodriver/issues/614 и единственное предлагаемое решение — driver.switchTo().defaultContent() . Это может исправить мою процедуру создания скриншотов, но элемент, которого я жду, находится внутри фрейма содержимого, поэтому я не могу использовать это исправление для ожидания.


person Mikhail Ramendik    schedule 16.05.2017    source источник


Ответы (3)


Похоже, кадр перезагружается с новой ссылкой, пока вы ждете элемент 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;
    }
  };
}
person Florent B.    schedule 16.05.2017
comment
Спасибо! Это сработало. (Я изменил его, чтобы использовать отдельное определение класса вместо инициализации фигурных скобок). В конце концов я нашел проблему на трекере geckodriver, и с этим ответом я знал, как оставить комментарий. Я сделал это. Проблема находится на github.com/mozilla/geckodriver/issues/614. - person Mikhail Ramendik; 17.05.2017

Не уверен, что это поможет вам, но когда я столкнулся с этим сообщением об ошибке, я смог обойти его, выполнив:

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

Без переключателей драйвера я бы получил ошибку мертвого объекта.

person jwest    schedule 08.02.2019

Видеть,

Должен быть формат, который я даю ниже:

  1. Сначала переключитесь на кадр. (Сначала переключитесь на значение по умолчанию, если вы уже находитесь в другом кадре).

  2. Выполните свое действие (нажмите на любой элемент)

  3. Снова переключитесь на контент по умолчанию. (если вы не переключите его обратно, это создаст проблему).

         driver.switchTo().defaultContent();
    
         driver.switchTo().frame(locator or name of the frame);
    
    
         driver.click(your element locator);
    
    
         driver.switchTo().defaultContent();
    
person Saurabh Gupta    schedule 09.08.2020