Решение задания 1: Правила именования
Файлы для тестирования должны начинаться с test_ или заканчиваться на _test. Функции тестов должны начинаться с test_.
# Правильные имена файлов:
test_calculator.py
calculator_test.py
# Правильная функция теста:
def test_sum():
calculator = Calculator()
assert calculator.sum(4, 5) == 9
# Неправильно (pytest не найдёт):
def check_sum(): # нет префикса test_
assert True
def TestSum(): # PascalCase не распознаётся
assert True
Решение задания 2: Фикстура Calculator
# test_calculator.py
import pytest
from calculator import Calculator
@pytest.fixture
def calculator():
"""Создаёт новый экземпляр Calculator для каждого теста."""
return Calculator()
# Фикстура передаётся как аргумент — pytest внедряет её автоматически
def test_sum(calculator):
assert calculator.sum(4, 5) == 9
def test_avg(calculator):
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 5]
assert calculator.avg(numbers) == 5
Почему фикстура лучше, чем создание объекта в каждом тесте? При изменении конструктора Calculator достаточно обновить только фикстуру — все тесты подхватят изменение автоматически.
Решение задания 3: Проверка исключения
def test_division_by_zero(calculator):
# pytest.raises() — контекстный менеджер для проверки исключений
# match= проверяет текст сообщения через re.search
with pytest.raises(ArithmeticError, match="На ноль делить нельзя"):
calculator.div(10, 0)
# В этом примере проверяется:
# 1. Что ArithmeticError действительно поднимается
# 2. Что текст ошибки содержит "На ноль делить нельзя"
# Если исключение НЕ поднято — тест упадёт с Failed
Решение задания 4: Маркировки
import sys
import pytest
from calculator import Calculator
# 1. Пропуск теста
@pytest.mark.skip(reason="Тест временно отключён")
def test_skip_example():
assert True
# 2. Условный пропуск
@pytest.mark.skipif(sys.version_info < (3, 8), reason="Требуется Python 3.8")
def test_version_dependent():
calculator = Calculator()
assert calculator.sum(4, 5) == 9
# 3. Пользовательская маркировка
@pytest.mark.positive_test
def test_sum():
calculator = Calculator()
assert calculator.sum(4, 5) == 9
@pytest.mark.positive_test
def test_div():
calculator = Calculator()
assert calculator.div(10, 2) == 5
# Запуск тестов по маркировке:
pytest -m positive_test
# pytest.ini — регистрация маркера (избегает предупреждений):
[pytest]
markers =
positive_test: Тесты для позитивных сценариев
Решение задания 5: Преимущества pytest
- Скорость выполнения: тесты запускаются быстро, особенно при повторных запусках в CI.
- Устранение человеческого фактора: автоматизация исключает ошибки ручного выполнения тестов.
- Удобное управление тестами: группировка с помощью маркировок и фильтры (
-k,-m). - Генерация отчётов: pytest предоставляет детализированные отчёты о результатах тестов.
- Простота написания: минимальная настройка, лаконичный синтаксис — нет необходимости наследоваться от TestCase.
- Изоляция тестов через фикстуры: каждый тест получает свежий объект, тесты не влияют друг на друга.