Привет, дорогие коллеги! В прошлой статье мы разобрали с вами один из наиболее удобных и гибких, на мой взгляд, способов построить фреймворк для проекта по автоматизации тестирования на Python. В качестве примера я приводил автотесты для API. Сегодня же я хочу поделиться с вами небольшим гайдом (или шпаркалкой, кому как удобнее) по одному из аспектов UI — тестирования. Если быть конкретным, речь идет о грамотных ожиданиях в тестах.
Наверное, каждый, кто уже более или менее погрузился в автоматизацию, уже не раз слышал либо понял сам, что использовать в тестах функцию sleep из стандартного модуля Python — это плохая практика, да и вообще моветон. Так вот. Для того, чтобы избежать косых вглядов коллег и просто не напороться в один момент на вилы в собственных тестах, предлагаю вам разобраться, как и когда использовать специальный модуль Selenium-a — Expected Conditions, который управляет теми самыми ожиданиями. Начнем.
БАЗА. Что, как и зачем?
В Selenium есть два основных типа ожидания: неявное (implicity_wait) и явное (WebDriverWait).
-
Неявное ожидание. Когда мы говорим Selenium: «Если ты при открытии страницы браузера сразу не можешь найти искомый элемент, не кричи сразу «тревога, мы все уронили», а сначала подожди n секунд, и уже потом, если элемент так и не появился, выдавай ошибку». Конструкция выглядит так: browser. implicity_wait(n). Вместо n, как вы уже догадались, нужное нам количество секунд. Рекомендую это также выносить в фикстуру вместе с инициализацией browser (о фикстурах и файле conftest.py я рассказывал в прошлой статье). Например:
-
Явное ожидание. Мы говорим Selenium: «Жди n секунд, пока не выполнится конкретное условие/событие (expected_conditions), и потом проверяй это условие». Такое подход наиболее гибкий и является стандартом. Выглядит это примерно следующим образом:
#Сначала импорт нужных модулей from selenium.webdriver.support.ui import WebDriverWait # as EC принято называть для сокращения длинного "expected_conditions" from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # Инициализируем ожидатор:) и говорим ему жди 10 секунд wait = WebDriverWait(browser, 10) element = wait.until(EC.условие(By.локатор, "значение_локатора"))
Это примерный базовый синтаксис для понимания конструкции в целом. Далее я как раз расскажу о том, какие же условия бывают.
Примечание: приведенная ниже классификация является исключительно авторской и представлена для удобства восприятия.
Группа условий № 1. Проверка присутствия видимости элемента
Как правильно наиболее часто используемая группа условий (на моей практике).
-
presence_of_element_located((locator))
— Что делает: Ждет, пока элемент появился в DOM-дереве страницы.
— Когда использовать:
— Когда нужно убедиться, что элемент загрузился в HTML — коде
— Когда работаем с «невидимыми» элементами
— Доп. заметки:
— Элемент может быть в DOM — дереве, но невидим на странице
— Самое «слабое» ожидание, но самое быстрое, если видимость не имеет значения -
visability_of_element_located((locator))
— Что делает: Ждет, пока элемент не только появится в DOM — дереве, но и станет видимым на странице
— Когда использовать:
— Практически в 90% случаев. Чтобы кликнуть, ввести текст, как-то повзаимодействовать с элементом, нужно, чтобы он появился. -
element_to_be_clickable((locator))
— Что делает: Ждет, пока элемент станет видимым И активным (enabled).
— Когда использовать:
— Всегда перед кликом на кнопку, ссылку или чекбокс. Фактически, решает проблему, когда кнопка уже видима, но еще неактивна (задизейблена).
— Доп. заметки:
— На мой взгляд, самое сильное и надежное ожидание перед кликом.
Группа № 2. Проверка состояния элемента
Используются для проверки атрибутов, текста и т.д.
-
text_to_be_present_in_element((locator), »ожидаемый текст»)
— Что делает: Ждет, пока внутри указанного элемента появится ожидаемый текст
— Когда использовать:
— Когда ждем, пока на странице обновится какой-то счетчик, статус или сообщение после выполнения определенного действия. Например: после добавления товара в корзину, мы ждем, пока в элементе с id «cart_counter» появится текст «1». -
invisibility_of_element_located((locator))
— Что делает: Ждет, пока элемент станет невидимым или полностью исчезнет из DOM.
— Когда использовать:
— Когда ждем, пока исчезнет какой-нибудь спиннер загрузки (лоадер)
— Когда проверяем, что после удаления элемент действительно пропал со страницы.
Группа № 3. Работа с alert -ами
Это группа специализированных ожиданий для работы со всплывающими окнами.
-
alert_is_present()
— Что делает: Ждет, пока на странице не появится стандартное окно alert, confirm или prompt.
— Когда использовать:
— При тестировании функционала, вызывающего данные окна.
— Доп. заметки:
— Этот тип ожидания (метод ожидания) не принимает локатор. Он возвращает объект alert, с которым мы будем работать (alert.accept(), alert.dismiss())
С классификацией, кажется, все. Как все мы знаем, прочитать информацию это одно, совсем другое — увидеть на примере. Поэтому набросал для вас небольшой пример использования:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # Представим, что тестируем форму логина LOGIN_BUTTON = (By.CSS_SELECTOR, '#login-button') USERNAME_INPUT = (By.ID, 'username') ERROR_MESSAGE = (By.CLASS_NAME, 'error-message') LOAD_SPINNER = (By.CSS_SELECTOR, '.loader') # Инициализируем ждуна, с неявным типом ожиданием wait = WebDriverWait(browser, 15) # Вводим имя пользователя (применяем ожидание появления элемента на странице) username = wait.until(EC.visability_of_element_located(USERNAME_INPUT)) username.send_keys('testuser') # Кликаем на кнопку (после того, как дождались, пока она стала кликабельной) login_button = wait.until(EC.element_to_be_clickable(LOGIN_BUTTON)) login_button.click() # Теперь ждем, пока исчезнет спиннер загрузки, который появился после клика load_spinner = wait.until(EC.invisibility_of_element_located(LOAD_SPINNER)) # К примеру мы не ввели пароль и ожидаем появления сообщения об ошибке после спиннера wait.untill(EC.text_to_be_present_in_element(ERROR_MASSAGE, 'Пароль не может быть пустым, дружочек'))
Этот пример максимально простой и показывает, как можно комбинировать различные типы ожидания, чтобы наши автотесты не «моргали». На этом сегодня, пожалуй, у меня все. Конструктивная критика и замечания приветствуются, плюсы в карму ценятся, ибо надеюсь кому-то изложенный мной материал будет полезен. Всем добра!
ссылка на оригинал статьи https://habr.com/ru/articles/935900/
Добавить комментарий