pytest -v/-vv, --tb опции, --pdb, --lf/--ff, чтение сообщений об ошибках
Вы уже написали 50 тестов. 3 из них падают. Как быстро найти причину и исправить?
Цель: научиться эффективно отлаживать тесты и читать сообщения об ошибках pytest.
pytestРезультат:
============================= test session starts ==============================
collected 10 items
tests/test_bank.py .F.F..... [100%]
=================================== FAILURES ===================================
_______________________________ test_withdraw __________________________________
def test_withdraw():
> account.withdraw(200)
E ValueError: Insufficient funds
tests/test_bank.py:25: ValueError
========================== 1 failed, 9 passed in 0.12s =========================
Проблемы:
pytest -vРезультат:
tests/test_bank.py::test_create_account PASSED [ 10%]
tests/test_bank.py::test_deposit PASSED [ 20%]
tests/test_bank.py::test_withdraw FAILED [ 30%]
✅ Теперь видно каждый тест!
pytest -vvРезультат для параметризованных тестов:
tests/test_bank.py::test_deposit[100-50-150] PASSED [ 20%]
tests/test_bank.py::test_deposit[0-100-100] PASSED [ 40%]
✅ Показывает параметры для каждого теста!
# Разработка: хочу видеть все тесты
pytest -v
# Отладка параметризованных тестов
pytest -vv
# CI/CD: минимальный вывод для скорости
pytestpytest --tb=shortРезультат:
=================================== FAILURES ===================================
_______________________________ test_withdraw __________________________________
tests/test_bank.py:25: in test_withdraw
account.withdraw(200)
E ValueError: Insufficient funds
✅ Только суть ошибки (без полного stacktrace)
pytest --tb=long✅ Полный путь ошибки (где именно она произошла)
pytest --tb=no✅ Только статистика (для CI когда логи большие)
--tb=auto # Автоматический (default)
--tb=long # Полный stacktrace
--tb=short # Короткий stacktrace
--tb=line # Только строка с ошибкой
--tb=no # Без stacktraceРекомендации:
--tb=short — для большинства случаев ✅--tb=long — когда ошибка глубоко в коде--tb=no — для CI (чтобы логи не раздувались)pdb (Python Debugger) — встроенный отладчик Python, который позволяет остановить программу в нужном месте, изучить значения переменных и найти причину бага без перезапуска тестов.
pytest --pdbЧто происходит:
Результат:
=================================== FAILURES ===================================
_______________________________ test_withdraw __________________________________
def test_withdraw():
> account.withdraw(200)
tests/test_bank.py:25
(Pdb) _
✅ Вы внутри теста! Можете проверить что угодно прямо здесь и сейчас.
(Pdb) account.balance
100
(Pdb) print(account.balance)
100
(Pdb) account.deposit(50)
(Pdb) account.balance
150
(Pdb) c # Continue (продолжить выполнение)
(Pdb) q # Quit (выйти из pdb)def test_complex_calculation():
"""Тест сложного расчёта"""
user = User("Alice", 25)
account = BankAccount(1000)
result = calculate_interest(account, user.age)
assert result == 50 # FAILEDВ pdb:
(Pdb) result
45 # Ага, получили 45 вместо 50!
(Pdb) calculate_interest(account, 25)
45 # Для возраста 25 получается 45 (не 50!)
# Нашли баг в тесте! Expected должно быть 45, не 50# Первый запуск: 10 тестов, 3 упали
pytest
# Повторный запуск: только 3 упавших теста
pytest --lf # last-failed✅ Быстро проверяем что баги исправлены!
pytest --ff # failed-first✅ Ускоряет обнаружение новых ошибок!
pytest -x # stop on first failure✅ Не тратим время на остальные тесты — сразу чиним первую ошибку!
pytest --maxfail=3 # Остановиться после 3 ошибок✅ Баланс между -x (слишком рано) и без флага (слишком поздно)
pytest tests/test_bank.py::test_withdraw -vv --pdb# 1. Запускаем все тесты
pytest
# 2. Смотрим только упавшие
pytest --lf -vv
# 3. Отлаживаем первый упавший
pytest --lf -x --pdb
# 4. После исправления — снова только упавшие
pytest --lfpytest --tb=no -x -q=================================== FAILURES ===================================
_______________________________ test_deposit ___________________________________
def test_deposit():
account = BankAccount(100)
account.deposit(50)
> assert account.balance == 200
E assert 150 == 200
E + where 150 = <BankAccount object at 0x...>.balance
tests/test_bank.py:15: AssertionError
Как читать:
> — строка с ошибкойE assert 150 == 200 — что пошло не так (получили 150, ожидали 200)E + where — откуда взялось значение 150Решение: ожидаемое значение неверно — должно быть 150, не 200.
=================================== FAILURES ===================================
_______________________________ test_withdraw __________________________________
def test_withdraw():
account = BankAccount(100)
> account.withdraw(200)
tests/test_bank.py:25:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def withdraw(self, amount):
if amount > self.balance:
> raise ValueError("Insufficient funds")
E ValueError: Insufficient funds
src/bank_account.py:32: ValueError
Решение: тест пытается снять 200, но на счёте только 100 — это корректное поведение! Нужно либо изменить тест, либо добавить pytest.raises.
E AttributeError: 'BankAccount' object has no attribute 'get_balance'
Решение: опечатка в названии метода (get_balance вместо balance) или метод не реализован.
E TypeError: deposit() missing 1 required positional argument: 'amount'
Решение: забыли передать аргумент amount.
pytest -vpytest --lf -vv --tb=shortpytest --lf -x --pdbpytest --lfpytestpytest -v/-vv — детальный вывод тестов--tb опции — контроль stacktrace--pdb — интерактивная отладка--lf/--ff — умное переиспользование упавших тестов-x/--maxfail — ранняя остановкаВы завершили курс «Pytest с нуля»! Теперь вы умеете писать базовые тесты, организовывать их в проекте, тестировать классы и ошибки, писать чистые тесты с AAA-паттерном, параметризовать тесты, группировать их маркерами, использовать фикстуры и отлаживать падения.
Что дальше? Переходите к более продвинутым темам: мокам и патчингу, coverage, плагинам и хукам, асинхронному тестированию.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.