Чем отличаются юнит-тесты от интеграционных тестов

Ответ

Юнит-тест (Unit Test) проверяет наименьшую изолированную часть кода (модуль, функцию, класс). Интеграционный тест (Integration Test) проверяет взаимодействие нескольких компонентов системы между собой.

Критерий Юнит-тесты Интеграционные тесты
Цель Проверить корректность логики одного модуля Убедиться, что компоненты правильно работают вместе
Изоляция Внешние зависимости (БД, API) заменяются моками Используют реальные или тестовые зависимости (тестовая БД)
Скорость Очень быстрые Значительно медленнее
Область Узкая, сфокусированная Широкая, охватывает несколько слоев

В пирамиде тестирования юнит-тесты составляют основу (их должно быть больше всего), а интеграционные тесты находятся на следующем уровне.

Пример юнит-теста (проверка одной функции):

# a_module.py
def is_strong_password(password: str) -> bool:
    return len(password) >= 8 and any(c.isdigit() for c in password)

# test_a_module.py
def test_is_strong_password():
    assert is_strong_password("password123") == True
    assert is_strong_password("short") == False
    assert is_strong_password("no_digits") == False

Пример интеграционного теста (проверка связки "сервис + БД"):

# user_service.py
class UserService:
    def __init__(self, db_session):
        self.db = db_session

    def create_user(self, name):
        user = User(name=name)
        self.db.add(user)
        self.db.commit()
        return user

# test_user_service.py
def test_user_creation_in_db(test_db_session): # test_db_session - реальное подключение к тестовой БД
    service = UserService(test_db_session)
    user = service.create_user("John Doe")

    # Проверяем, что пользователь действительно появился в базе данных
    retrieved_user = test_db_session.query(User).filter_by(name="John Doe").one()
    assert user.id == retrieved_user.id