Pytest – тестирование

онлайн тренер по питону
Онлайн-тренажер Python 3 для начинающих

Теория без воды. Задачи с автоматической проверкой. Подсказки на русском языке. Работает в любом современном браузере.

начать бесплатно

Введение

Тестирование — неотъемлемая часть разработки. Без тестов сложно быть уверенным, что код работает правильно и не сломается при следующем обновлении. Pytest – тестирование — это современный, гибкий и удобный фреймворк для автоматического тестирования на Python.

Pytest завоевал популярность благодаря лаконичному синтаксису, расширяемости и мощной системе фикстур. Он превосходит стандартный unittest по удобству и скорости разработки.

Установка и первый тест

Установка:

bash
pip install pytest

Создайте файл test_example.py:

python
def test_addition(): assert 2 + 2 == 4

Запуск:

bash
pytest

Pytest сам найдёт все тесты, начинающиеся с test_.

Структура и запуск тестов

  • Тестовые файлы: test_*.py или *_test.py

  • Тестовые функции: def test_...():

Запуск:

bash
pytest tests/ # тесты в каталоге pytest test_file.py::test_func # конкретный тест

Ассерты и проверки

В Pytest можно использовать обычные assert:

python
def test_multiply(): assert 3 * 3 == 9

Проверка исключений:

python
import pytest def divide(a, b): return a / b def test_zero_division(): with pytest.raises(ZeroDivisionError): divide(1, 0)

Фикстуры (fixtures)

Фикстуры позволяют подготовить данные, создать подключения и очистить ресурсы после теста:

python
import pytest @pytest.fixture def sample_data(): return {"name": "Ivan", "age": 30} def test_user(sample_data): assert sample_data["age"] == 30

Область действия:

  • function — по умолчанию

  • module, class, session

Параметризация тестов

python
@pytest.mark.parametrize("a, b, result", [ (2, 3, 5), (10, 20, 30), ]) def test_add(a, b, result): assert a + b == result

Группировка и маркировка тестов

python
@pytest.mark.math def test_square(): assert 4**2 == 16

Запуск по марке:

bash
pytest -m math

Пропуск и ожидание ошибок

python
@pytest.mark.skip(reason="Временно отключено") def test_temp(): ... @pytest.mark.xfail def test_fail(): assert 1 == 2

Тестирование исключений

Контекстный менеджер:

python
with pytest.raises(ValueError, match="Invalid"): raise ValueError("Invalid data")

Mock-объекты и monkeypatch

python
def get_api_key(): return "real_key" def test_mock(monkeypatch): monkeypatch.setattr("__main__.get_api_key", lambda: "mocked") assert get_api_key() == "mocked"

Работа с временными файлами и каталогами

python
def test_file(tmp_path): file = tmp_path / "example.txt" file.write_text("Hello") assert file.read_text() == "Hello"

Интеграция с CI/CD (GitHub Actions, GitLab)

GitHub Actions:

yaml
- name: Run tests run: pytest

GitLab:

yaml
test: script: - pytest --junitxml=report.xml

Плагины и расширения Pytest

  • pytest-cov — покрытие тестами

  • pytest-django — интеграция с Django

  • pytest-asyncio — асинхронные тесты

Установка:

bash
pip install pytest-cov

Запуск с отчётом покрытия:

bash
pytest --cov=my_module

Отладка и вывод ошибок

  • -v — подробный вывод

  • -s — отключение подавления stdout

  • --tb=short|no|line — настройка traceback

Сравнение с unittest и другими фреймворками

Фреймворк Ассерты Фикстуры Параметры Расширения Простота
Pytest Да Да Да Много Очень высокая
unittest Нет Частично Нет Мало Средняя
nose2 Да Да Да Меньше Умеренная

Часто задаваемые вопросы (FAQ)

1. Что такое Pytest?
Это фреймворк для написания и запуска автоматических тестов на Python.

2. В чём преимущества Pytest?
Простой синтаксис, фикстуры, параметризация, мощные плагины.

3. Как запускать отдельные тесты?
pytest test_file.py::test_func

4. Поддерживает ли Pytest асинхронность?
Да, через плагин pytest-asyncio.

5. Где хранятся фикстуры?
В conftest.py — общий файл фикстур для всех тестов.

6. Можно ли использовать Pytest с Django, FastAPI?
Да, с помощью соответствующих плагинов.

Полный справочник по ключевым функциям и модулям библиотеки Pytest для Python

Установка

bash
pip install pytest

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

bash
pytest # ищет тесты в текущей директории pytest tests/ # запуск в папке tests pytest test_file.py # запуск конкретного файла

Структура и правила именования

Правило Описание
Файл должен начинаться с test_ Например: test_math.py
Функции должны начинаться с test_ Например: def test_add(): ...
Классы тестов называются Test* и не должны иметь __init__()  
python
def test_sum(): assert 1 + 1 == 2

Основные утверждения (assert)

Утверждение Проверка
assert x == y Равенство
assert x != y Неравенство
assert x in y Вхождение
assert condition Истинность
assert isinstance(x, T) Проверка типа

Pytest сам формирует понятные сообщения об ошибках при падении assert.


Фикстуры (@pytest.fixture)

Назначение Описание
@pytest.fixture Определяет подготовку данных для теста
Автоматически передаются в тестовые функции по имени параметра  
Можно использовать yield для финализации  
python
import pytest @pytest.fixture def user(): return {"name": "Ваня", "age": 30} def test_user(user): assert user["age"] > 20

Автоматический запуск кода до и после теста

python
@pytest.fixture def resource(): setup = open("tmp.txt", "w") yield setup setup.close()

Параметризация

Декоратор Описание
@pytest.mark.parametrize("param", [...]) Повторяет тест с разными значениями
python
import pytest @pytest.mark.parametrize("a,b,result", [(1, 2, 3), (4, 5, 9)]) def test_add(a, b, result): assert a + b == result

Группировка в классы

python
class TestMath: def test_add(self): assert 1 + 1 == 2 def test_sub(self): assert 5 - 2 == 3

Скип и ожидание ошибок

Декоратор Описание
@pytest.mark.skip Пропустить тест
@pytest.mark.skipif(cond, reason="...") Пропустить при условии
@pytest.mark.xfail Ожидается, что тест упадет
python
@pytest.mark.skip(reason="Не готово") def test_beta(): ...

Проверка исключений

python
import pytest def raise_error(): raise ValueError("Ошибка") def test_error(): with pytest.raises(ValueError): raise_error()

Команды CLI (важные параметры)

Команда Описание
-v Подробный вывод
-q Краткий вывод
--maxfail=1 Остановиться после первой ошибки
--tb=short/line/no Уровень отображения трассировки
-k "substr" Запуск тестов по подстроке в имени
-m marker Фильтрация по маркерам

Маркеры (@pytest.mark.*)

Маркер Назначение
@pytest.mark.slow Пользовательский маркер
@pytest.mark.db Для группировки тестов
Указывается через -m в CLI pytest -m "db and not slow"
ini
# pytest.ini [pytest] markers = slow: медленный тест db: доступ к базе

Конфигурация (pytest.ini)

ini
[pytest] addopts = -v --tb=short testpaths = tests

Плагины

Плагин Назначение
pytest-cov Покрытие кода
pytest-mock Моки через monkeypatch и mocker
pytest-django Интеграция с Django
pytest-asyncio Поддержка async/await