Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Заполнение формы на Selenium + Python


(Alexander Petrovich) #1

Привет. Работаю над тестом, который проверяет работу некоторой формы. Трюк в том, что в зависимости от настроек количество заполняемых полей в форме может изменяться. Поэтому, чтобы не морочаться с локацией каждой отдельной строки, пытаюсь изобрести более ленивый метод. Для начала, например, проверяем валидацию. Дл этого хочу стереть данные из всех текстовых полей.

def clear_all_fields(driver):
    text_fields = driver.find_elements_by_xpath("//form[@id='create_order_form']/div/div/div[@class='form-line']/div[@class='form-inputs']/input[@type='text']")
    for field in text_fields:
       field.clear()

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

def clear_all_fields(driver):
    text_fields = driver.find_elements_by_xpath("//form[@id='create_order_form']/div/div/div[@class='form-line']/div[@class='form-inputs']/input[@type='text']")
    not_displayed_text_fields = driver.find_elements_by_xpath("//form[@id='create_order_form']/div/div/div[@style='display: none;']")
    for field in text_fields:
        if field not in not_displayed_text_fields:
            field.clear()

И тут собственно начинаются грабли. При прогоне говорит, что

Traceback (most recent call last):
  File "test_order.py", line 81, in test_order
    clear_all_fields(self.driver)
  File "test_order.py", line 68, in clear_all_fields
    field.clear()
  File "/usr/local/lib/python2.7/dist-packages/selenium-2.15.0-py2.7.egg/selenium/webdriver/remote/webelement.py", line 53, in clear
    self._execute(Command.CLEAR_ELEMENT)
  File "/usr/local/lib/python2.7/dist-packages/selenium-2.15.0-py2.7.egg/selenium/webdriver/remote/webelement.py", line 194, in _execute
    return self._parent.execute(command, params)
  File "/usr/local/lib/python2.7/dist-packages/selenium-2.15.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 153, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python2.7/dist-packages/selenium-2.15.0-py2.7.egg/selenium/webdriver/remote/errorhandler.py", line 147, in check_response
    raise exception_class(message, screen, stacktrace)
WebDriverException: Message: u'Element is not currently interactable and may not be manipulated'
 

Очевидно, селениум всё равно обращается к скрытым полям и пытается их очистить. Помогите разобраться, где я туплю


(Дмитрий Жарий) #2

 

Признаюсь честно, не в Питоне, не в Selenium я не силен, но не могу удержатся чтобы что-то не посоветовать.

Вероятно, driver.find_elements_by_xpath возвращает список Python’овских объектов класса  WebElement.

Вы вызывает динамический поиск два раза, и необязательно то, что два Питоновских объекта, ссылающихся на один и тот же элемент страницы будут равны.

Скорее всего, это будут два разных Питоновских объекта. 


(Mykhailo Poliarush) #3

WebDriverException: Message: u'Element is not currently interactable and may not be manipulated'

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

я думаю, надо посмотреть в тело страницы и посмотреть на этот элемент, у него определенно есть какая-то особенность, которая не правиться webdriver


(Alexander Petrovich) #4

find_elements_by_xpath в обоих случаях точно правильный (я его малость изменил, далее в комментарии указан). С таким xpath firebug отображает именно те элементы, которые мне надо.

Кажется грабли именно в

for field in text_fields:
        if field not in not_displayed_text_fields:

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

1. text_fields = driver.find_elements_by_xpath("//div[@class='form-line']/div[@class='form-inputs']/input[@type='text']")

2. not_displayed_text_fields = driver.find_elements_by_xpath("//div[@style='display: none;' and @class='form-line']/div[@class='form-inputs']/input[@type='text']")

3.

for field in text_fields:
        if field not in not_displayed_text_fields:

 


(Mykhailo Poliarush) #5

1. зайди в интерпретатор пайтона и шаг за шагом выполни твои действия, посмотри какие списки возвращаются в двух случаях

2. также посмотри, чтобы количество элементов соответствовало количеству элементов отображаемых на странице

3. вывести все можно так [e for e in d.find_elements_by_xpath("//input")]

4. также можно включить твою проверки в try except block и выводит элементы для которых сработал try

5. походу когда происходит сравнение, то webdriver пытается обратиться к спрятаному элементу, может быть надо перегрузить сравнение объектов

надо бы конечно html страницы, чтобы мог подсказать более конкретно

 


(Alexander Petrovich) #6

Вот наверное try except'ом и буду пользоваться. Очень странно, но селениум вообще не видит этого массива невидимых элементов.

Подскажите, есть ли способ проверить, отображён ли элемент? То есть не искать костыль в xpath, а просто выбрать из первого массива только видимые.


(Mykhailo Poliarush) #7

ну есть три метода, которые ты можешь использовать для каждого элемента

 

  is_displayed(self)
      Whether the element would be visible to a user
 
  is_enabled(self)
      Whether the element is enabled.
 
  is_selected(self)
      Whether the element is selected.
 
Тебе надо первый

(Alexander Petrovich) #8

В общем, нашёл решение, достаточно гибкое.

def make_an_order(driver):
    text_fields = driver.find_elements_by_xpath("//div[@class='form-line']/div[@class='form-inputs']/input[@type='text")
    for field in text_fields:
        try:
            field.clear()
        except:
            pass


(Mykhailo Poliarush) #9

да, все просто до безобразия