Разделы портала

Онлайн-тренинги

.
Легкое веб-тестирование с Python, Pytest и Selenium WebDriver, часть 2: создание проекта по тест-автоматизации на Python
19.06.2020 00:00

Автор: Энди Найт (Andy Knight)
Оригинал статьи
Перевод: Ольга Алифанова

Часть 1

Теперь, когда мы знаем, зачем нам Web UI-тестирование и какими должны быть наши цели, настроим проект тест-автоматизации на Python, используя pytest!


Почему Python?

Python – один из самых популярных из доступных языков программирования. На нем пишут бэкэнды сайтов, проводят анализ данных, создают скрипты для администрирования системы… Его синтаксис чист, читабелен и элегантен, и отлично подходит как для экспертов, так и для начинающих. К тому же все мыслимое и немыслимое всего лишь в одном импорте от вас. Логично, что Python также отлично подходит для тест-автоматизации. Его лаконичность позволяет больше фокусироваться на тесте, и меньше – на коде. Тестировщики без особых навыков программирования, как правило, изучают Python быстрее, нежели другие языки вроде Java или C#. Python прекрасен для быстрого погружения в автоматизацию!

Что такое pytest?

В сердце любого проекта функциональной тест-автоматизации лежит "корневой" тест-фреймворк. Фреймворк имеет дело со структурой тест-кейсов, выполнением тестов, и отчетности о пройденных и упавших проверках. Это основа, к которой добавляются дополнительные пакеты и код (вроде Selenium WebDriver).

pytest – один из лучших тест-фреймворков Python. Он прост, масштабируем, и "Пайтоничен". Тест-кейсы пишутся как функции, а не классы. Падения тест-утверждений выводятся в отчете с реальными значения ми. При помощи плагинов можно добавить покрытие кода, красивые отчеты, и параллельный запуск. pytest может интегрироваться с другими фреймворками вроде Django и Flask. Согласно опросу разработчиков Python-2018, pytest – самый популярный тест-фреймворк для Python.

Приступим

Давайте создадим наш первый тест-проект на Python! Если вы еще этого не сделали, пожалуйста, скачайте и установите Python 3. Затем создайте новую директорию для проекта:

  1. $ mkdir python-webui-testing
  2. $ cd python-webui-testing

Создавая новый проект Python, я всегда создаю виртуальное окружение для его зависимостей. В этом случае у проектов на одной машине не будет конфликтующих версий пакетов. Я пользуюсь pipenv, потому что он упрощает дело. Для глобальной установки pipenv введите:

  1. $ pip install pipenv

Затем установите pytest для вашего нового проекта:

  1. $ pipenv install pytest --dev

Pipenv добавит в ваш проект два новых файла: Pipfile и Pipfile.lock. Pipfile определяет требования проекта, а Pipfile.lock "блокирует" явные версии, которыми проект будет пользоваться. Опция “–dev” в команде означает, что пакет pytest будет использоваться для разработки, а не для деплоя.

Первый тест

По традиции большинство проектов размещают все тесты в директории tests/. Давайте следовать традиции:

  1. $ mkdir tests
  2. $ cd tests

Создайте модуль Python с названием test_math.py для нашего первого теста, и добавьте следующий код:

  1. def test_addition():
  2. assert 1 + 1 == 2

Тестам, написанным при помощи pytest, обычно не требуется много кода. Эти две строчки – полнофункциональный тест-кейс! Тест-кейс записан как функция, а не как класс. Для такого базового теста импорты не нужны. Нативный оператор контроля Python используется вместо кастомных контрольных вызовов.

Запуск тестов

Давайте запустим наш новый тест. Смените директорию на корневую директорию проекта, и вызовите модуль pytest:

  1. $ cd ..
  2. $ pipenv run python -m pytest
  3. ============================= test session starts ==============================
  4. platform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.12.0
  5. rootdir: /Users/andylpk247/Programming/automation-panda/python-webui-testing
  6. collected 1 item
  7. tests/test_math.py . [100%]
  8. =========================== 1 passed in 0.02 seconds ===========================

Наш первый тест пройден!

Как pytest обнаружил наш тест? По имени: pytest будет искать тест-функции с именем test_* в модулях по имени test_*.py. Интересно, что pytest не требует файла __init__.py в тест-директориях.

Упавшие тесты

Что будет, если тест упадет? Давайте добавим другой тест с багом, чтобы проверить это:

  1. def test_subtraction():
  2. diff = 1 - 1
  3. assert diff == 1

Теперь при запуске Pytest мы увидим вот что:

  1. $ pipenv run python -m pytest
  2. ============================= test session starts ==============================
  3. platform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.12.0
  4. rootdir: /Users/andylpk247/Programming/automation-panda/python-webui-testing
  5. collected 2 items
  6. tests/test_math.py .F [100%]
  7. =================================== FAILURES ===================================
  8. _______________________________ test_subtraction _______________________________
  9. def test_subtraction():
  10. diff = 1 - 1
  11. > assert diff == 1
  12. E assert 0 == 1
  13. tests/test_math.py:13: AssertionError
  14. ====================== 1 failed, 1 passed in 0.08 seconds ======================

Тест test_subtraction упал с "F" вместо ".". Более того, pytest выводит сообщения трассировки, показывающие упавшее утверждение вместе с модулем и номером строки. Отметим, что реальные значения каждого выражения в утверждении тоже отображаются: diff оценивается как 0, что явно не равно 1. Круто! Эта самодиагностика утверждений очень помогает разбираться в падениях тестов.

Исправим баг:

  1. def test_subtraction():
  2. diff = 1 - 1
  3. assert diff == 0

И перезапустим эти тесты:

  1. $ pipenv run python -m pytest
  2. ============================= test session starts ==============================
  3. platform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.12.0
  4. rootdir: /Users/andylpk247/Programming/automation-panda/python-webui-testing
  5. collected 2 items
  6. tests/test_math.py .. [100%]
  7. =========================== 2 passed in 0.02 seconds ===========================

Мы снова на верном пути.

Параметризованные тесты

Что, если нам нужно запустить тест-процедуру с разными сочетаниями ввода? У pytest для этого есть декоратор! Составим тест для умножения с параметризованным вводом:

  1. import pytest
  2. @pytest.mark.parametrize(
  3. "a,b,expected",
  4. [(0, 5, 0), (1, 5, 5), (2, 5, 10), (-3, 5, -15), (-4, -5, 20)])
  5. def test_multiplication(a, b, expected):
  6. assert a * b == expected

На этот раз нужно импортировать модуль pytest. Декоратор @pytest.mark.parametrize будет заменять наборы значений для аргументов тест-функции, запуская функцию по разу для каждого набора. Повторный запуск тестов покажет больше пройденных тестов:

  1. $ pipenv run python -m pytest
  2. ============================= test session starts ==============================
  3. platform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.12.0
  4. rootdir: /Users/andylpk247/Programming/automation-panda/python-webui-testing
  5. collected 7 items
  6. tests/test_math.py ....... [100%]
  7. =========================== 7 passed in 0.03 seconds ===========================

Супер! Параметры – отличный способ реализовать тестирование, управляемое через данные.

Sweet! Parameters are a great way to do data-driven testing.

Верификация исключений

Pytest относится к необрабатываемым исключениям, как к падениям теста. На самом деле оператор контроля просто выдает исключение для регистрации падения. Что, если нам нужно убедиться, что выдается правильное исключение? Используйте pytest.raises с нужным типом исключения – например, так:

  1. def test_divide_by_zero():
  2. with pytest.raises(ZeroDivisionError):
  3. 1 / 0

Rerun the tests to make sure all is well:

  1. $ pipenv run python -m pytest
  2. ============================= test session starts ==============================
  3. platform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.12.0
  4. rootdir: /Users/andylpk247/Programming/automation-panda/python-webui-testing
  5. collected 8 items
  6. tests/test_math.py ........ [100%]
  7. =========================== 8 passed in 0.04 seconds ===========================

Отлично. Математика все еще работает!

Больше информации

В этой главе мы рассказали об основах, но pytest умеет и многое другое. Изучите официальный сайт pytest, чтобы узнать о более продвинутых фичах фреймворка. Далее мы разберемся, как использовать фикстуры и новые плагины.