PyTest Tutorial: установка, написание и запуск тестов на Python с уверенностью
Что такое PyTest?
PyTest — мощный open-source фреймворк тестирования, позволяющий разработчикам писать лаконичные, масштабируемые тест-кейсы для Python-проектов — будь то юнит-тесты, интеграционные или end-to-end API-проверки. Поддерживает параллельное выполнение, внедрение фикстур, параметризацию и богатую отчётность «из коробки».
Почему выбирать PyTest?
- Простой, читаемый синтаксис, снижающий boilerplate
- Автоматическое обнаружение и запуск тестов
- Запуск конкретных тестов или групп через
-kи маркеры - Встроенная поддержка параллельных прогонов через
pytest-xdist - Расширяемость через фикстуры, хуки и плагины
- Бесплатен и активно поддерживается сообществом
Установка PyTest
Установите последнюю стабильную версию через pip:
pip install pytest
Проверьте установку:
pytest --version
Для контроля версии можно закрепить релиз, например: pip install pytest==7.4.0.
Первые шаги: базовый тест
Создайте директорию проекта и добавьте тестовый файл test_sample1.py:
import pytest
def test_file1_method1():
x = 5
y = 6
assert x + 1 == y, "Addition failed"
assert x == y, "Values should match"
def test_file1_method2():
x = 5
y = 6
assert x + 1 == y, "Addition failed"
Запустите тестовый набор:
pytest
Пример вывода:
==================== test session starts ====================
collected 2 items
test_sample1.py F. [100%]
=================================== FAILURES ===================================
...
Понимание утверждений (assertions)
Утверждения PyTest ведут себя как стандартные Python assert. При провале тест останавливается, и PyTest сообщает точную позицию и сообщение:
assert "hello" == "Hai", "Mismatched greeting"
Правила обнаружения тестов
- Файлы должны начинаться с
test_или заканчиваться на_test.py. - Тестовые функции должны начинаться с
test_. - Другие файлы или функции игнорируются, если не указаны явно.
Запуск конкретных тестов
Выполнить все тесты в директории:
pytest
Запустить один файл:
pytest test_sample1.py
Фильтр по подстроке:
pytest -k method1 -v
Запуск по маркеру:
pytest -m set1
Параллельное выполнение
Установите плагин xdist и запустите 4-воркерный параллельный прогон:
pip install pytest-xdist pytest -n 4
Использование фикстур
Определите переиспользуемую логику настройки однажды и внедряйте в тесты:
import pytest
@pytest.fixture
def supply_data():
return [25, 35, 45]
def test_compare_with_first(supply_data):
assert supply_data[0] == 25
Разместите код фикстур в conftest.py для обмена между несколькими тестовыми модулями.
Параметризованные тесты
Запустите один тест с множеством входных данных:
import pytest
@pytest.mark.parametrize("a, b, expected", [(5, 5, 10), (3, 5, 8)])
def test_add(a, b, expected):
assert a + b == expected
Пропуск и ожидаемые провалы
Используйте маркеры для пропуска или ожидания провалов без загрязнения результатов:
import pytest
@pytest.mark.skip(reason="Feature not yet available")
def test_future_feature():
pass
@pytest.mark.xfail(reason="Known bug")
def test_known_issue():
assert 1 == 2
Генерация XML-отчётов
Создайте JUnit-совместимый XML-файл для CI-пайплайнов:
pytest -v --junitxml=result.xml
Практический пример: тестирование публичного API
Ниже — минимальный фреймворк, тестирующий https://reqres.in/:
# conftest.py
import pytest
@pytest.fixture
def base_url():
return "https://reqres.in/api"
# test_list_user.py
import requests, json
import pytest
@pytest.mark.parametrize("user_id, first_name", [(1, "George"), (2, "Janet")])
def test_valid_user(base_url, user_id, first_name):
resp = requests.get(f"{base_url}/users/{user_id}")
data = json.loads(resp.text)
assert resp.status_code == 200
assert data["data"]["id"] == user_id
assert data["data"]["first_name"] == first_name
def test_invalid_user(base_url):
resp = requests.get(f"{base_url}/users/50")
assert resp.status_code == 404
# test_login_user.py
import requests, json
import pytest
def test_login_success(base_url):
payload = {"email": "test@test.com", "password": "something"}
resp = requests.post(f"{base_url}/login/", data=payload)
data = json.loads(resp.text)
assert resp.status_code == 200
assert data["token"] == "QpwL5tke4Pnpja7X"
def test_login_missing_password(base_url):
payload = {"email": "test@test.com"}
resp = requests.post(f"{base_url}/login/", data=payload)
data = json.loads(resp.text)
assert resp.status_code == 400
assert data["error"] == "Missing password"
Заключение
Это руководство покрыло установку PyTest, написание понятных тестов, использование фикстур и маркеров, параллельный запуск, генерацию XML-отчётов и построение простого API-тестового набора. С этими основами вы можете масштабировать свои практики тестирования на Python с уверенностью.
Python
- Как установить WordPress на Google Cloud: пошаговое руководство
- Coded UI Test: комплексное руководство для начинающих по фреймворку автоматизации
- Узнайте свой ключ безопасности сети: простые шаги для поиска и защиты Wi‑Fi
- Wi-Fi Calling: как работает, зачем нужен и чем полезен
- Исследование 6G: будущее ультрабыстрой связи
- Экспертное руководство: установка док-левелеров для максимальной эффективности
- Понимание тестирования частичных разрядов: защита высоковольтного оборудования
- Предотвращение кавитации насоса: причины, симптомы и как избежать
- Лужение меди: Техники и советы для прочных, надежных соединений
- Объяснение задержки технического обслуживания: стратегии устранения