Автоматизация тестирования веб-приложений с помощью Selenium и Python

Раздел: Тестирование -> Автоматизация браузера

Основы работы с Selenium WebDriver в Python

Selenium WebDriver позволяет автоматизировать действия браузера для тестирования веб-приложений. Для начала необходимо установить библиотеку selenium и соответствующий драйвер (например, ChromeDriver).

Базовый скрипт: открытие страницы и взаимодействие с элементом

from selenium import webdriver
from selenium.webdriver.common.by import By

# Инициализация драйвера
driver = webdriver.Chrome()
driver.get('https://example.com')

# Поиск элемента по идентификатору и ввод текста
input_field = driver.find_element(By.ID, 'search')
input_field.send_keys('Selenium')

# Нажатие кнопки
button = driver.find_element(By.CLASS_NAME, 'submit-btn')
button.click()

# Закрытие браузера
driver.quit()

Python selenium (selenium в python)

Пояснения: find_element возвращает первый найденный элемент, send_keys имитирует ввод текста, click нажимает кнопку. После завершения работы драйвер необходимо закрыть через quit(), чтобы освободить ресурсы.

Типичные проблемы:

  • Ошибка NoSuchElementException - элемент не найден. Решение: проверить локатор, использовать ожидания (см. вариант 2).
  • Ошибка WebDriverException - проблема с драйвером. Убедитесь, что версия драйвера соответствует версии браузера.

Варианты решений для типовых задач

Как найти элемент по разным локаторам?

Используйте класс By с различными стратегиями:

from selenium.webdriver.common.by import By

# По ID
elem = driver.find_element(By.ID, 'myId')

# По имени
elem = driver.find_element(By.NAME, 'username')

# По классу
elem = driver.find_element(By.CLASS_NAME, 'container')

# По css-селектору
elem = driver.find_element(By.CSS_SELECTOR, 'div.container > a')

# По xpath (точный или относительный)
elem = driver.find_element(By.XPATH, '//input[@type="submit"]')

Каждый локатор подходит для разных ситуаций. Xpath наиболее гибкий, но медленнее CSS.

Распространённая ошибка:

Неправильный синтаксис CSS или XPath. Проверьте локатор через консоль браузера (например, $$('.container') для CSS).

Как дождаться появления элемента на странице?

Используйте явные ожидания через WebDriverWait и expected_conditions:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)  # ждать до 10 секунд
button = wait.until(EC.element_to_be_clickable((By.ID, 'submit')))
button.click()

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

Проблема:

TimeoutException - элемент не появился за отведённое время. Увеличьте таймаут или проверьте правильность локатора. Также может помочь добавление неявного ожидания (implicitly_wait) для всех поисков.

Как работать с выпадающим списком (select)?

Используйте класс Select:

from selenium.webdriver.support.ui import Select

select_element = driver.find_element(By.ID, 'country')
select = Select(select_element)
select.select_by_visible_text('Россия')      # выбор по видимому тексту
select.select_by_value('ru')                  # по значению атрибута value
select.select_by_index(2)                    # по индексу

Это удобно для обычных HTML-списков. Если элемент не является . Проверьте тэг. Для кастомных выпадающих списков применяйте последовательность кликов.

Как обработать всплывающее окно alert?

Переключитесь на alert, примите или отклоните:

alert = driver.switch_to.alert
alert.accept()           # нажать ОК
alert.dismiss()           # отмена
text = alert.text         # прочитать текст

Метод switch_to.alert возвращает объект Alert. После обработки управление возвращается на страницу.

Ошибка:

NoAlertPresentException - alert не появился. Используйте явное ожидание EC.alert_is_present().

Как выполнить JavaScript в браузере?

Метод execute_script позволяет исполнять любой JS-код:

# Скролл страницы
driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')

# Получение значения через JS
value = driver.execute_script('return document.title;')
print(value)

# Изменение атрибута элемента
elem = driver.find_element(By.ID, 'block')
driver.execute_script('arguments[0].style.display = "none";', elem)

JS-инъекции полезны для скролла, манипуляции DOM и обхода ограничений тестирования.

Проблема:

Не все действия можно эмулировать через JS (например, наведение мыши). Используйте ActionChains для сложных взаимодействий.

Как сделать скриншот окна?

Метод save_screenshot сохраняет изображение текущего окна:

driver.save_screenshot('screenshot.png')

Для скриншота конкретного элемента используйте elem.screenshot('element.png').

Ошибка:

Размер скриншота может быть ограничен viewport. Для полной страницы понадобится скролл и склейка (библиотека Selenium-Screenshot).

Как работать с iframe?

Переключитесь в iframe по индексу, имени или элементу:

# По индексу
driver.switch_to.frame(0)

# По имени или ID
driver.switch_to.frame('contentFrame')

# По веб-элементу
iframe = driver.find_element(By.TAG_NAME, 'iframe')
driver.switch_to.frame(iframe)

# После работы внутри iframe вернуться в основной документ
driver.switch_to.default_content()

Все последующие поиски будут выполняться внутри выбранного iframe.

Ошибка:

NoSuchFrameException - iframe не существует. Проверьте правильность индекса или локатора. Не забудьте вернуться в default_content, если нужно работать с другими фреймами.

Продвинутые примеры использования Selenium

Пример 1: Автоматизация многостраничной формы

Пример
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get('https://example.com/form')

# Страница 1: заполнение полей
driver.find_element(By.NAME, 'firstName').send_keys('Иван')
driver.find_element(By.NAME, 'email').send_keys('ivan@mail.com')
driver.find_element(By.CLASS_NAME, 'next-btn').click()

# Страница 2: ожидание загрузки и выбор опции
wait = WebDriverWait(driver, 10)
option = wait.until(EC.element_to_be_clickable((By.XPATH, '//input[@value="option2"]')))
option.click()

submit = driver.find_element(By.ID, 'submit')
submit.click()

# Проверка успешного завершения
success_msg = WebDriverWait(driver, 5).until(
    EC.presence_of_element_located((By.CLASS_NAME, 'success'))
)
print('Форма отправлена:', success_msg.text)

driver.quit()

Пояснение: Используются явные ожидания для каждого шага, чтобы избежать ошибок при переходах между страницами.

Форма отправлена: Спасибо за регистрацию!

Пример 2: Извлечение данных из таблицы в pandas DataFrame

Пример
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('https://quotes.toscrape.com/table')

# Находим таблицу
table = driver.find_element(By.TAG_NAME, 'table')
rows = table.find_elements(By.TAG_NAME, 'tr')

data = []
for row in rows:
    cols = row.find_elements(By.TAG_NAME, 'td')
    if cols:
        data.append([col.text for col in cols])

df = pd.DataFrame(data)
print(df.head())
driver.quit()

Пояснение: Собираем все строки таблицы, извлекаем текст из ячеек. Результат конвертируется в DataFrame.

0  1  2
0  Имя     Возраст  Город
1  Анна   25       Москва
2  Борис  30       СПб

Пример 3: Работа с несколькими вкладками

Пример
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('https://example.com')

# Открываем новую вкладку через JS
driver.execute_script('window.open("_blank");')

# Переключаемся на последнюю вкладку
driver.switch_to.window(driver.window_handles[-1])
driver.get('https://google.com')
print('Текущая вкладка:', driver.title)

# Вернуться на первую вкладку
driver.switch_to.window(driver.window_handles[0])
print('Первая вкладка:', driver.title)

driver.quit()

Пояснение: window_handles - список всех открытых вкладок. Переключение по индексу или по дескриптору.

Текущая вкладка: Google
Первая вкладка: Example Domain

Пример 4: Сохранение и использование кук для сессии

Пример
import pickle
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://example.com/login')

# Выполняем вход (заполняем логин/пароль и жмём кнопку) ...
# После успешного входа сохраняем куки
cookies = driver.get_cookies()
with open('cookies.pkl', 'wb') as f:
    pickle.dump(cookies, f)

# В новом сеансе загружаем куки
driver2 = webdriver.Chrome()
driver2.get('https://example.com')  # обязательно сначала открыть домен
with open('cookies.pkl', 'rb') as f:
    loaded_cookies = pickle.load(f)
for cookie in loaded_cookies:
    driver2.add_cookie(cookie)

driver2.get('https://example.com/dashboard')
# Теперь пользователь авторизован
driver2.quit()

Пояснение: Куки сохраняются в файл, затем для новой сессии добавляются перед переходом на защищённую страницу.

(Нет вывода, но после загрузки кук страница дашборда открывается авторизованной)

Пример 5: Headless режим с настройками ChromeOptions

Пример
from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--window-size=1920x1080')

driver = webdriver.Chrome(options=options)
driver.get('https://example.com')

print(driver.title)
driver.save_screenshot('headless_screenshot.png')
driver.quit()

Пояснение: Headless-режим запускает браузер без графического интерфейса. Полезно для серверов и CI.

Example Domain

Selenium в Python - comments

En
Python selenium (python)