Как использовать Selenium с модульным тестом Python

В предыдущем посте мы исследовали объектную модель страницы для написания более удобного в сопровождении и повторного использования кода. В этом посте мы увидим использование Selenium с модулем unittest Python.

Модульные тесты используются для тестирования наименьших тестируемых частей программы. Среда модульного тестирования Python предоставляет функции управления тестами, такие как установка предварительных и постусловий, проверка результата с ожидаемым результатом и создание отчета о выполнении теста.

unittest модуль состоит из пяти функций

  • Загрузчик тестов: загружает тестовые случаи и наборы.
  • Тестовый пример: реализует интерфейс, необходимый для запуска теста.
  • Набор тестов: группирует набор тестовых случаев.
  • Test Runner: предоставляет работающий интерфейс для выполнения теста.
  • Отчет о тестировании. Отображает статус прохождения/непрохождения выполненных тестовых случаев и общее затраченное время.

Мы должны наследовать наш класс от класса TestCase модуля unittest, чтобы создать тестовый пример. Нам также нужно добавить тестовый метод в наш производный класс. Наконец, мы должны использовать метод assert, предоставляемый классом TestCase, для проверки и отчета о состоянии теста.

Ниже приведены некоторые из наиболее часто используемых методов утверждения.

  • assertEqual(a, b): Проверяет, если a == b
  • assertNotEqual(a, b): Проверяет, если a != b
  • assertTrue(a): Проверяет, истинно ли значение bool(a)
  • assertFalse(a): Проверяет, имеет ли bool(a) значение False
  • assertIs(a, b): проверяет, является ли a b
  • assertIsNone(a): Проверяет, является ли a None
  • assertIn(a, b): Проверяет, есть ли a в b
  • assertNotIn(a, b): Проверяет, не находится ли a в b
  • assertIsInstance(a, b): Проверяет, является ли экземпляр (a, b)
  • assertRaises(exception, func): Проверяет, возникает ли исключение при вызове func

Во время выполнения теста выполнение продолжается со следующего теста, только если проверка утверждения проходит успешно. Если оператор assert терпит неудачу, выполнение теста завершается сообщением об ошибке.

Набор тестов состоит из одного или нескольких тестовых наборов, а тестовый набор может содержать один или несколько тестов.

Следующий фрагмент кода представляет собой базовый скелет реализации тестового примера.

class SampleTestCase(unittest.TestCase):

Мы создаем наш класс путем создания подкласса unittest.TestCase, который реализует интерфейс, необходимый для выполнения тестов.

def setUp(self):
    # initalization code
    pass

Метод setUp запускается перед каждым тестом в тестовом примере. Его можно использовать для запуска фиксированного набора действий перед выполнением теста.

def test_method(self):
    # test code
    pass

Наши фактические тесты функциональности находятся в методах, начинающихся с test.

def tearDown(self):
    # clean up code
    pass

Метод tearDown запускается после каждого теста и позволяет отменить действия, выполняемые методом setUp.

Существуют также методы setUpClass и tearDownClass, используемые с декоратором @classmethod. Они запускаются только один раз в тестовом примере до/после всех тестов, а не для каждого теста.

if __name__ == "__main__":
    unittest.main()

Наконец, unittest.main() предоставляет интерфейс командной строки для запуска тестового сценария.

Использование Selenium с модулем unittest

Мы будем использовать классы объектов страницы из предыдущего поста в наших тестах.

Тесты главной страницы

Прохождение примера

Мы создаем экземпляр WebDriver до того, как все тесты начнут выполняться. Если вы не хотите создавать и уничтожать экземпляр WebDriver до и после каждого теста, вы можете поместить его в метод setUpClass вместо метода setUp.

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

Этот тестовый метод проверяет функциональность отправки вопроса. Он использует методы, определенные в классе объекта страницы для домашней страницы, такие как enter_code, enter_question или submit_question.

Этот тест также показывает пример использования объекта компонента. Метод navigate_to_bopi класса PythonDoctorHomePage делегирует этот запрос классу Navigation.

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

После выполнения всех тестов в тестовом примере выполняется метод tearDownClass. Мы выходим из браузера, который мы запустили в методе setUpClass, и освобождаем ресурсы.

Тесты страницы BOPI

Тесты для второй страницы также имеют ту же структуру, что и описанная выше.

Запустите следующую команду, чтобы выполнить тесты

python -m unittest -v

Отчет о тестировании распечатывается на стандартный вывод, как показано ниже.

# output
test_best_practices_filter (test_bopi.TestBOPIPage) ... ok
test_navigate_to_homepage (test_bopi.TestBOPIPage) ... ok
test_navigate_to_about (test_home.HomePageTest) ... ok
test_navigate_to_bopi_page (test_home.HomePageTest) ... ok
test_navigate_to_feedback (test_home.HomePageTest) ... ok
test_open_link (test_home.HomePageTest) ... ok
test_submit_question (test_home.HomePageTest) ... ok
------------------------------------------------------------------
Ran 7 tests in 48.165s
OK

Если вы хотите попробовать более простой в использовании и гибкий фреймворк, вы можете проверить пакет pytest. Он не является частью официального дистрибутива Python, поэтому вы должны сначала установить его как сторонний пакет.

То, что нужно запомнить

  • Среда модульного тестирования Python предоставляет функции управления тестами, такие как установка предварительных и постусловий, проверка результата с ожидаемым результатом и создание отчета о выполнении теста.
  • Мы должны наследовать наш класс от класса TestCase модуля unittest, чтобы создать тестовый пример. Нам также нужно добавить тестовый метод в наш производный класс. Наконец, мы должны использовать метод assert, предоставляемый классом TestCase, для проверки и отчета о состоянии теста.
  • Во время выполнения теста выполнение продолжается со следующего теста, только если проверка утверждения проходит успешно. Если оператор assert терпит неудачу, выполнение теста завершается сообщением об ошибке.
  • Метод setUp запускается перед каждым тестом в тестовом примере. Его можно использовать для запуска фиксированного набора действий перед выполнением теста.
  • Метод tearDown запускается после каждого теста и позволяет отменить действия, выполняемые методом setUp.
  • Методы setUpClass и tearDownClass, используемые с декоратором classmethod. Они запускаются только один раз в тестовом примере до/после всех тестов, а не для каждого теста.
  • Тесты не запускаются в том порядке, в котором мы их пишем, поэтому вы должны писать их так, чтобы они не вызывали побочных эффектов при запуске в другом порядке.

В следующем посте мы увидим запуск нашего скрипта автоматизации на удаленной машине.

Спасибо за уделенное время.

использованная литература

  1. https://docs.python.org/3/library/unittest.html
  2. https://realpython.com/python-testing/
  3. https://www.techbeamers.com/selenium-python-test-suite-unittest/
  4. https://www.seleniumeasy.com/python/selenium-webdriver-unittest-example
  5. https://medium.com/@mashood.snhu/automated-unit-testing-of-a-web-application-in-python-de426afda5a3
  6. https://blog.testproject.io/2019/07/16/web-ui-testing-python-pytest-selenium-webdriver/