DebanjanB: Вам известна какая-то документация / книга, в которой подробно объясняются все HTML DOM, Framesets, загрузка кадров, взаимодействие с javascript, вызовы AJAX и т. Д. И т. Д. И т. Д.?

я довольно сложная настройка веб-страницы, которую мне нужно протестировать, она содержит вложенные фреймы.

В реальной задаче код селена загружает новое содержимое веб-страницы, содержащее фрейм, на который я хочу перейти. Чтобы избежать явных ожиданий, я попробовал следующий фрагмент кода:

self.driver.switch_to_default_content()
WebDriverWait(self.driver, 300).\
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame1')))
WebDriverWait(self.driver, 300).\
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame2')))

Тем не менее этот фрагмент всегда терпит неудачу и приводит к следующей ошибке:

  ...
  File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/wait.py", line 71, in until
    value = method(self._driver)
  File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/expected_conditions.py", line 247, in __call__
    self.frame_locator))
  File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/expected_conditions.py", line 402, in _find_element
    raise e
WebDriverException: Message: TypeError: can't access dead object

Однако, если я использую сон в дополнение:

time.sleep(30)
self.driver.switch_to_default_content()
WebDriverWait(self.driver, 300).\
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame1')))
WebDriverWait(self.driver, 300).\
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame2')))

Селен способен найти кадр внутри кадра и переключиться на него. Похоже, что в случае ошибки селен переключается на «frame1», в то время как «frame2» еще не загружен, но «frame2» загружается в каком-то другом экземпляре «frame1» или не распознается селеном (может быть, ошибкой?). Так что теперь селен находится внутри некоторого «frame1» и по некоторым причинам не понимает, что «frame2» был загружен.

Единственный способ, которым я могу это исправить (без долгого сна), это использовать этот уродливый кусок кода:

    mustend = time.time() + 300
    while time.time() < mustend:
        try:
            self.driver.switch_to_default_content()
            self.driver.switch_to.frame(self.driver.find_element_by_id("frame1"))
            self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))               
            break
        except WebDriverException as e:
            self.log("Sleeping 1 sec")
            time.sleep(1)
    if time.time() > mustend:
        raise TimeoutException

Поэтому всякий раз, когда я получаюWebDriverException (мертвый объект), я иду к кадру верхнего уровня и пытаюсь переключиться на внутренний кадр - кадр за кадром.

Есть ли другой подход, который я могу попробовать?

Дополнительная информация

Фреймы вложены, то есть frame2 находится внутри frame1.
 suit14 дек. 2017 г., 12:26
Можете ли вы добавить кусок вашего HTML с фреймами?
 Alex14 дек. 2017 г., 16:14
Я постараюсь скопировать части HTML, но не уверен, как я могу сделать это легко ...
 Alex14 дек. 2017 г., 13:35
@suit: это будет невозможно ...

Ответы на вопрос(2)

class nested_frames_to_be_available_and_switch:
    def __init__(self, *args):
        """
        :param args: locators tuple of nested frames (BY.ID, "ID1"), (BY.ID, "ID2"), ...
        """
        self.locators = args

    def __call__(self, driver):
        try:
            for locator in self.locators:
                driver.switch_to.frame(driver.find_element(*locator))
        except WebDriverException:
            driver.switch_to_default_content()
            return False
        return True

WebDriverWait(driver, 300).until(nested_frames_to_be_available_and_switch((By.ID, 'frame1'), (By.ID, 'frame1')))

Но, может быть, в этом нет необходимости ... Чтобы сказать, мне нужно увидеть ваш HTML DOM.

 Alex14 дек. 2017 г., 15:26
Это похоже на мой подход, но в некоторых последовательных именах. Я люблю это...
 suit14 дек. 2017 г., 16:34
@ Алекс, я еще раз взглянул на классы EC. * И исправил свой код

WebDriverException: Message: TypeError: can't access dead object не глядя на следующее:

ПолныйHTML DOMПрисутствиеFramesetПрисутствиеFramesПоследовательность изFrame LoadingПрисутствиеJavaScript а такжеAJAX Calls в соответствующем<iframe> теги

На данный момент стоит отметить, что изначальноSelenium всегда фокусируется наdefault_content, Вот несколько подходов для работы с вложеннымиframes а такжеframesets :

Если обаframe1 а такжеframe2 находятся на том же уровне и подTop Level Browsing Context мы должны:

self.driver.switch_to.frame(self.driver.find_element_by_id("frame1"))
self.driver.switch_to_default_content()
self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))

Еслиframe2 вложен вframe1, чтобы переключиться сframe1 вframe2 мы должны:

self.driver.switch_to_default_content()
self.driver.switch_to.frame(self.driver.find_element_by_id("frame1"))
//code
self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))

Еслиframe2 а такжеframe3 внутриframe1 затем, чтобы перейти отframe2 вframe3 мы должны:

self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))
self.driver.switch_to.frame(self.driver.find_element_by_id("frame1"))
self.driver.switch_to.frame(self.driver.find_element_by_id("frame3"))

Еслиframe2 а такжеframe3 находится в пределахframeset23 который находится внутриframe1 затем, чтобы перейти отframe2 вframe3 мы должны:

self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))
#ignore presence of frameset23
self.driver.switch_to.frame(self.driver.find_element_by_id("frame1"))
#ignore presence of frameset23
self.driver.switch_to.frame(self.driver.find_element_by_id("frame3"))
Лучший подход с правильным WebDriverWait:

Имея дело сframes а такжеframesets мы всегда должны побуждатьWebDriverWait со следующимexpected_conditions :

Переключение междуFrames :

frame_to_be_available_and_switch_to_it

Взаимодействовать сWebElements вFrames :

element_to_be_clickable
 Alex05 июл. 2018 г., 11:51
DebanjanB: Вам известна какая-то документация / книга, в которой подробно объясняются все HTML DOM, Framesets, загрузка кадров, взаимодействие с javascript, вызовы AJAX и т. Д. И т. Д. И т. Д.?
 Alex14 дек. 2017 г., 16:23
Перепробовал все это в том числеWebDriverWait, При этом я получаю ту же ошибку (т.е. вижу вопрос, где я используюWebDriverWait...)

Ваш ответ на вопрос