← Назад к вопросам

Проводишь ли макетное тестирование

1.7 Middle🔥 151 комментариев
#Теория тестирования

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Провожу ли я макетное тестирование?

Да, конечно. Макетное тестирование (Mock Testing) — это неотъемлемая часть моей повседневной практики как QA Automation инженера. Я не просто провожу его, а считаю ключевой стратегией для создания стабильных, быстрых и изолированных автоматизированных тестов. В современной разработке, особенно в парадигме микросервисной архитектуры и непрерывной интеграции/непрерывного развертывания (CI/CD), без моков эффективное тестирование практически невозможно.

Макет (Mock) — это специальный объект, который имитирует поведение реального зависимого компонента системы (например, базы данных, внешнего API, файловой системы или другого микросервиса) в контролируемых условиях. Это позволяет тестировать код изолированно, фокусируясь только на его бизнес-логике.

Зачем я активно использую моки в автотестах?

  • Изоляция тестируемого модуля (Unit/Integration): Главная цель. Тест должен падать только из-за бага в тестируемом коде, а не из-за сбоя в стороннем сервисе или пустой тестовой БД.
  • Повышение скорости выполнения тестов: Вызовы к реальной базе данных, внешним API или файловой системе на порядки медленнее, чем работа с объектами в памяти. Моки исключают эти задержки.
  • Воспроизведение сложных и редких сценариев: С помощью моков легко смоделировать ситуации, которые сложно или дорого создать в реальной среде: таймауты сети, возврат специфических кодов ошибок (например, 500 Internal Server Error или 403 Forbidden), нестандартные ответы.
  • Декремент зависимостей: Тесты можно писать и запускать, даже если реальная зависимость еще не готова или временно недоступна (разработка ведется параллельно).
  • Контроль над непредсказуемыми данными: Например, текущая дата/время или генератор случайных чисел. Мок позволяет "зафиксировать" время, чтобы поведение теста было детерминированным.

Практический пример: тестирование сервиса, зависящего от внешнего API

Представим сервис WeatherService, который получает данные от внешнего API и обрабатывает их.

# weather_service.py - Тестируемый сервис
import requests

class WeatherService:
    def __init__(self, api_client):
        self.api_client = api_client

    def get_tomorrow_temperature(self, city):
        # Предположим, метод fetch_weather делает HTTP-запрос
        data = self.api_client.fetch_weather(city)
        return data['forecast']['tomorrow']['temp']

Без моков тест делал бы реальный HTTP-запрос. Это плохо. Вот как это выглядит с использованием библиотеки unittest.mock в Python:

# test_weather_service.py - Автотест с использованием Mock
import unittest
from unittest.mock import Mock, patch
from weather_service import WeatherService

class TestWeatherService(unittest.TestCase):

    def test_get_tomorrow_temperature_success(self):
        # 1. ARRANGE: Создаем макет (mock) для api_client
        mock_api_client = Mock()

        # Задаем жестко предопределенное поведение метода fetch_weather
        mock_api_client.fetch_weather.return_value = {
            'forecast': {
                'tomorrow': {'temp': 22}
            }
        }

        # 2. ACT: Инжектируем мок в тестируемый сервис и вызываем метод
        service = WeatherService(api_client=mock_api_client)
        result = service.get_tomorrow_temperature('London')

        # 3. ASSERT: Проверяем результат и удостоверяемся, что мок был вызван корректно
        self.assertEqual(result, 22)
        # Важно: проверяем, что мок был вызван ровно один раз с правильным аргументом
        mock_api_client.fetch_weather.assert_called_once_with('London')

    # Пример теста на ошибку с использованием контекстного менеджера patch
    def test_get_tomorrow_temperature_api_failure(self):
        with patch('weather_service.requests') as mock_requests:
            # Мокаем метод, чтобы он выбрасывал исключение
            mock_requests.get.side_effect = ConnectionError("Network is down")
            service = WeatherService(api_client=mock_requests)

            with self.assertRaises(ConnectionError):
                service.get_tomorrow_temperature('London')

Важные принципы, которых я придерживаюсь

  1. Не мокать то, что ты тестируешь. Мокаются только внешние зависимости.
  2. Сочетать с другими видами тестов. Макетное тестирование — мощный инструмент, но оно не заменяет интеграционные и сквозные (E2E) тесты, которые проверяют взаимодействие реальных компонентов. Я выстраиваю пирамиду тестирования, где на нижних уровнях (много unit-тестов с моками) — скорость и изоляция, а на верхних (меньше E2E) — проверка работы системы в целом.
  3. Проверять взаимодействие (Interaction Testing). Важно не только проверить возвращаемое значение, но и удостовериться, что тестируемый модуль корректно взаимодействует с зависимостями: вызывает правильные методы, с правильными аргументами и нужное количество раз (используя assert_called_with, assert_called_once и т.д.).
  4. Использовать специализированные библиотеки. В зависимости от стека технологий: Mockito/PowerMock для Java, Sinon.js для JavaScript, Moq для .NET, unittest.mock для Python.

Вывод: Проведение макетного тестирования — это не вопрос личного предпочтения, а профессиональная необходимость для создания качественной, поддерживаемой и надежной автоматизации. Это позволяет мне как инженеру быстро получать обратную связь о качестве кода, минимизировать "шум" в тестах и уверенно рефакторить систему, зная, что сломанная интеграция будет сразу обнаружена.