tests/ директория, именование test_*.py, импорты из src/, pytest discovery
В первом уроке вы запустили тест прямо в корне проекта. Но в реальных проектах тесты хранятся отдельно от кода.
Цель: научиться правильно организовывать тесты, чтобы проект был понятен вам и вашей команде.
Плохая структура:
my-project/
├── test_user.py
├── test_auth.py
├── test_api.py
├── user.py
├── auth.py
└── api.py
Проблемы:
cd pytest-tutorial
mkdir src
mkdir tests
# pytest-tutorial/
# ├── src/ # Код приложения
# ├── tests/ # Тесты
# └── .venv/ # Виртуальное окружение# src/calculator.py
def add(a, b):
"""Складывает два числа"""
return a + b
def subtract(a, b):
"""Вычитает второе число из первого"""
return a - b
def multiply(a, b):
"""Умножает два числа"""
return a * b# tests/test_calculator.py
from src.calculator import add, subtract, multiply
def test_add():
"""Тест сложения"""
assert add(2, 3) == 5
assert add(-1, 1) == 0
def test_subtract():
"""Тест вычитания"""
assert subtract(5, 3) == 2
assert subtract(0, 5) == -5
def test_multiply():
"""Тест умножения"""
assert multiply(3, 4) == 12
assert multiply(-2, 3) == -6pytest tests/ -vОжидаемый результат:
============================ test session starts ============================
collected 3 items
tests/test_calculator.py::test_add PASSED [ 33%]
tests/test_calculator.py::test_subtract PASSED [ 66%]
tests/test_calculator.py::test_multiply PASSED [100%]
============================= 3 passed in 0.02s =============================
✅ Pytest автоматически нашёл все тесты в tests/ директории!
pytest tests/test_calculator.py -vpytest tests/test_calculator.py::test_add -vPytest автоматически находит тесты по правилам именования:
# ✅ ХОРОШО — pytest найдёт
test_*.py # test_calculator.py, test_user.py
*_test.py # calculator_test.py, user_test.py
# ❌ ПЛОХО — pytest НЕ найдёт
calculator.py # Нет префикса test_
my_tests.py # Нет префикса test_Рекомендация: используйте test_*.py (стандарт в Python-сообществе).
# ✅ ХОРОШО — pytest найдёт
def test_addition():
pass
def test_user_creation():
pass
# ❌ ПЛОХО — pytest НЕ найдёт
def addition_test(): # Нет префикса test_
pass# ✅ ХОРОШО — pytest найдёт
class TestCalculator:
def test_add(self):
pass
# ❌ ПЛОХО — pytest НЕ найдёт
class Calculator: # Нет префикса Test
def test_add(self):
passКогда вы запускаете pytest, он:
tests/, игнорирует src/ и .venv/test_calculator.py, игнорирует helpers.pydef test_add(), игнорирует def helper_function()# Покажет список всех найденных тестов БЕЗ запуска
pytest --collect-onlyРезультат:
<Module tests/test_calculator.py>
<Function test_add>
<Function test_subtract>
<Function test_multiply>
Для сложных проектов используется зеркальная структура: tests/ повторяет структуру src/ для удобства навигации.
pytest-tutorial/
├── src/
│ ├── user/
│ │ ├── models.py
│ │ └── services.py
│ └── auth/
│ └── handlers.py
├── tests/
│ ├── user/
│ │ ├── test_models.py
│ │ └── test_services.py
│ └── auth/
│ └── test_handlers.py
└── pytest.ini
# tests/test_calculator.py
from calculator import add # ❌ ПЛОХОModuleNotFoundError: No module named 'calculator'
Исправление:
from src.calculator import add # ✅ ХОРОШОmy-project/
├── src/
└── my_tests/ ← ❌ pytest не найдёт (неправильное имя)
└── test_user.py
Исправление: переименуйте my_tests/ в tests/.
__init__.py (Python < 3.3)Для старых проектов может потребоваться touch src/__init__.py и touch tests/__init__.py. Но для современных проектов (Python 3.3+) это не обязательно!
tests/ директорию для организации файловsrc/ в тестыtest_*.py и def test_*()Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.
Далее: Тестируем классы и ошибки