Какие подходы используются для выявления ошибок в функциях при модульном тестировании в Python

«Какие подходы используются для выявления ошибок в функциях при модульном тестировании в Python» — вопрос из категории Тестирование, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для выявления ошибок в функциях используется модульное тестирование (unit testing), которое фокусируется на проверке отдельных компонентов (функций, методов) в изоляции.

Основные подходы и техники:

  1. Тестирование на основе сценариев (Case-based testing) Создаются тесты для различных входных данных, чтобы проверить все ветви логики:

    • Позитивные сценарии (Happy path): Проверка работы с корректными, ожидаемыми данными.
    • Негативные сценарии: Проверка обработки невалидных данных (неправильный тип, формат).
    • Граничные условия (Boundary cases): Тестирование крайних значений (например, 0, -1, пустые строки, максимальные значения).
  2. Проверки утверждений (Assertions) Использование assert для сравнения фактического результата работы функции с ожидаемым.

  3. Проверка исключений (Exception testing) Тест должен подтвердить, что функция корректно выбрасывает ожидаемое исключение при определённых условиях (например, деление на ноль).

  4. Изоляция с помощью моков (Mocking) Замена внешних зависимостей (базы данных, API, файловая система) на "заглушки" (mock-объекты). Это позволяет тестировать логику функции, не затрагивая другие части системы.

Пример с использованием pytest:

import pytest

def divide(a, b):
    """Функция для деления двух чисел."""
    if not isinstance(a, (int, float)) or not isinstance(b, (int, float)):
        raise TypeError("Both arguments must be numbers")
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero")
    return a / b

# 1. Позитивный сценарий
def test_divide_happy_path():
    assert divide(10, 2) == 5

# 2. Тестирование граничного условия
def test_divide_by_negative():
    assert divide(-10, 2) == -5

# 3. Проверка исключения ZeroDivisionError
def test_divide_by_zero_raises_exception():
    with pytest.raises(ZeroDivisionError):
        divide(10, 0)

# 4. Проверка исключения TypeError для невалидных данных
def test_divide_with_invalid_type_raises_exception():
    with pytest.raises(TypeError):
        divide(10, "a")

Ключевые инструменты:

  • pytest: Мощный и популярный фреймворк для тестирования.
  • unittest.mock: Встроенная библиотека для создания мок-объектов.
  • coverage.py: Инструмент для измерения процента кода, покрытого тестами.