Когда тестов и файлов с тестами становится много, возникают новые вопросы:
- Как группировать тесты?
- Как запустить на выполнение все тесты из одной директории?
- Если тестов очень много и они долгие, можно ли запустить их параллельно?
Для решения этих вопросов используют специальные тестовые фреймворки. Они помогают организовать структуру тестов и дают много полезного, например, удобный вывод. С большинством из этих возможностей мы познакомимся далее по курсу.
В Python-мире популярен фреймворк Pytest, на котором мы сосредоточимся в этом уроке.
Что такое Pytest
Python — один из немногих языков, в стандартную библиотеку которого уже включен тестовый фреймворк (он называется unittest). Было бы логично рассмотреть его здесь, но он глубоко завязан на классы, которые вы можете не знать. Поэтому здесь мы рассматриваем Pytest, который все равно популярнее встроенного фреймворка.
Далее мы создадим проект с нуля и добавим в него тесты.
Настройка и запуск
Создайте где-нибудь на вашем компьютере директорию с названием hexlet_pytest. Зайдите в нее и выполните команды:
# Установка poetry https://python-poetry.org/docs/#installation
poetry new . # Создание базовой структуры
poetry install # Установка зависимостей
Команда poetry new
создает болванку python-пакета и добавляет туда директорию для будущих тестов tests. Установите pytest с помощью poetry в группу dev с помощью команды poetry add -G dev pytest
. Проверьте, что все работает правильно:
poetry run pytest
# Ниже примерный вывод
platform darwin -- Python 3.8.2, pytest-5.4.3, py-1.10.0, pluggy-0.13.1
rootdir: /private/tmp/hexlet_pytest
collected 0 items
======= no tests ran in 0.01s =======
Теперь добавим немного исходного кода. Создайте файл hexlet_pytest/example.py. Обратите внимание, что в директории проекта команда создала директорию с таким же именем, как и директория самого проекта hexlet_pytest. Файл нужно создать внутри этой вложенной директории. Содержимое файла:
# Эта функция переворачивает переданную строку
def reverse(string):
return string[::-1]
Pytest ожидает, что тесты находятся в директории tests, которую располагают в корне проекта. Внутри этого каталога можно создавать любую структуру — Pytest найдет все тесты, которые там лежат.
Именование файлов с тестами должно быть таким: test_<name>.py. Как правило, в этой записи <name> соответствует имени файла, который тестируется.
Напишем наш первый тест. Создайте файл tests/test_example.py со следующим содержимым:
from hexlet_pytest.example import reverse
def test_reverse():
assert reverse('Hexlet') == 'telxeH'
def test_reverse_for_empty_string():
assert reverse('') == ''
Далее мы разберем структуру этого файла, а пока попробуем запустить тест на выполнение:
poetry run pytest
platform darwin -- Python 3.8.2, pytest-5.4.3, py-1.10.0, pluggy-0.13.1
rootdir: /private/tmp/hexlet-pytest
collected 2 items
tests/test_example.py .. [100%]
# Один тест запускается так
# poetry run pytest tests/test_example.py
https://replit.com/@hexlet/python-testing-pytest
Структура
Давайте еще раз посмотрим на файл с тестом:
from hexlet_pytest.example import reverse
def test_reverse():
assert reverse('Hexlet') == 'telxeH'
def test_reverse_for_empty_string():
assert reverse('') == ''
Каждый тест внутри файла — это функция, начинающаяся с префикса test_. Тестовых функций можно делать любое количество, все уже зависит от сложности тестируемого кода. Внутри функций проверки выполняются с помощью инструкции assert
.
Несмотря на схожесть со встроенной инструкцией в Python, инструкция assert
в Pytest работает немного по-другому. Попробуйте внести ошибку в исходную функцию и запустите тесты заново:
def test_reverse():
> assert reverse('Hexlet') == 'telxeH'
E AssertionError: assert 'Hexlet' == 'telxeH'
E - telxeH
E + Hexlet
tests/test_example.py:4: AssertionError
Вывод Pytest содержит не только исходное утверждение, но и результат вызова функции:
- Плюсом помечается то, что пришло
- Минусом помечается то, что ожидалось
Благодаря такому выводу, найти и исправить ошибку становится значительно проще.
В работе Pytest есть одна особенность. Если понадобится распечатать что-то на экран, то Pytest ничего не выведет. По умолчанию он перехватывает и подавляет весь вывод. Отключить это поведение можно с помощью флага -s
:
poetry run pytest -s
# Теперь видно все, что выводится с помощью print
Самостоятельная работа
- Выполните все шаги из этого урока
- Создайте репозиторий hexlet_pytest на GitHub
- Залейте код на GitHub
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.