Какой у вас опыт модульного (unit) тестирования?

«Какой у вас опыт модульного (unit) тестирования?» — вопрос из категории Автоматизация тестирования, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Имею опыт написания модульных тестов на Python (pytest/unittest) и JavaScript/TypeScript (Jest). Основная цель — проверка корректности работы отдельных изолированных единиц кода: функций, методов, классов.

Ключевые практики, которые я применяю:

  1. Изоляция: Использую моки (mocks) и стабы (stubs) для замены внешних зависимостей (база данных, API, файловая система).
  2. Читаемость: Именую тесты по шаблону should_[ожидаемое поведение]_when_[условие].
  3. Покрытие граничных случаев: Тестирую не только happy path, но и некорректные входные данные, пустые значения, предельные условия.
  4. Использование фикстур (pytest) и параметризации для устранения дублирования кода.

Пример модульного теста на Python с использованием pytest и моков:

import pytest
from unittest.mock import Mock, patch
from myapp.user_service import UserService
from myapp.database import Database

def test_get_user_by_id_success():
    """Тест должен вернуть данные пользователя, когда пользователь существует в БД."""
    # 1. Arrange (Подготовка)
    mock_db = Mock(spec=Database) # Создаём mock объекта БД
    expected_user = {'id': 1, 'name': 'Alice'}
    mock_db.get_user.return_value = expected_user # Задаём поведение мока
    service = UserService(db=mock_db) # Внедряем зависимость

    # 2. Act (Действие)
    result = service.get_user_profile(1)

    # 3. Assert (Проверка)
    assert result == expected_user
    mock_db.get_user.assert_called_once_with(user_id=1) # Проверяем вызов мока

# Пример параметризованного теста для проверки граничных случаев
@pytest.mark.parametrize('user_id, expected', [
    (0, None),  # Невалидный ID
    (999, None), # Несуществующий ID
    (1, {'id': 1, 'name': 'Alice'}),
])
def test_get_user_by_id_edge_cases(user_id, expected):
    mock_db = Mock()
    mock_db.get_user.return_value = expected
    service = UserService(db=mock_db)
    assert service.get_user_profile(user_id) == expected

Интегрировал модульные тесты в CI/CD (например, GitHub Actions) и использовал инструменты для анализа покрытия кода, такие как pytest-cov или istanbul.