Что такое «simulation testing» (тестирование в симулированной среде)?

Краткий тезис

Simulation testing — это метод тестирования AI-агентов, при котором агент запускается не в реальном окружении (настоящие API, базы данных, внешние сервисы), а в контролируемой симулированной среде, где все внешние взаимодействия подменяются моками, стабами или детерминированными симуляторами. Такой подход позволяет безопасно и дёшево проверять поведение агента в редких сценариях (edge cases), при сбоях (fault injection) и в условиях, которые невозможно или дорого воспроизвести в production.


1. Определение и контекст: зачем агентам симуляция?

AI-агент — это программа, которая автономно принимает решения и взаимодействует с внешним миром: вызывает REST API, отправляет запросы в базы данных, управляет сторонними сервисами, обрабатывает файлы. Реальное тестирование таких агентов наталкивается на проблемы:

  • Стоимость — каждый реальный call|вызов API (например, OpenAI, Stripe) стоит денег.
  • Нестабильность — внешние сервисы могут быть недоступны, менять поведение.
  • Невоспроизводимость — трудно повторно создать одно и то же состояние (погода, курс валют, остатки товаров).
  • Риск — агент может случайно сделать деструктивное действие (удалить запись, отправить письмо).

Simulation testing решает эти проблемы, заменяя внешние компоненты на симуляторы, которые работают предсказуемо, быстро и бесплатно.

ХарактеристикаРеальная средаСимулированная среда
Стоимость вызововЕсть (деньги, лимиты)Нет (все локально)
ВоспроизводимостьНизкая (зависит от внешних факторов)Высокая (детерминизм)
Контроль ошибокСложно спровоцировать 500, timeoutЛегко с fault injection
БезопасностьРиск изменения production данныхИзолированный sandbox

2. Основные компоненты симулированной среды

Чтобы создать симулированную среду для агента, понадобятся три ключевых компонента.

2.1 Mock API (имитация внешних HTTP-сервисов)

Mock API — это заглушка, которая принимает HTTP-запросы и возвращает предопределённые ответы. Часто используется библиотека WireMock (Java), Moto (для AWS), responses (Python), nock (Node.js).
Пример для Python с responses:

import responses
import requests

@responses.activate
def test_agent_calls_weather_api():
    # Настраиваем mock: любой запрос к weather API вернёт {"temp": 25}
    responses.add(
        responses.GET,
        "https://api.weather.com/v1/current",
        json={"temp": 25, "unit": "C"},
        status=200
    )
    # Агент делает настоящий вызов, но responses перехватывает его
    resp = requests.get("https://api.weather.com/v1/current")
    assert resp.json()["temp"] == 25

2.2 Stub Database (заглушка базы данных)

Вместо реальной PostgreSQL/MySQL используют SQLite in-memory или библиотеки-моки (например, mock_database для SQLAlchemy). Это позволяет изолировать тесты данных и быстро сбрасывать состояние.

2.3 Deterministic Simulator (детерминированный симулятор)

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

class TradingSimulator:
    def __init__(self):
        self.cash = 10000
        self.shares = 0
    
    def buy(self, price, quantity):
        if self.cash >= price * quantity:
            self.cash -= price * quantity
            self.shares += quantity
            return {"success": True, "new_shares": self.shares}
        return {"success": False, "error": "insufficient_funds"}

3. Методы simulation testing

3.1 Mock API (замена ответов)

Как описано выше. Главный приём: подменяются не только успешные ответы, но и все возможные HTTP-статусы (200, 201, 400, 401, 403, 500, 502).

3.2 Fault Injection (инъекция сбоев)

Fault injection — искусственное внесение ошибок в окружение: таймауты, медленные ответы (latency), сетевые ошибки (ConnectionError), невалидные JSON’ы. Это проверяет устойчивость агента (graceful degradation).

Пример с responses:

responses.add(
    responses.GET,
    "https://api.payments.com/charge",
    body=requests.ConnectionError("Simulated network failure")
)

3.3 Deterministic simulation (замена логики на предсказуемую)

Используется, когда внешний сервис слишком сложен для простого стаба. Например, симулятор рекомендательной системы возвращает заранее заданные топ-N товаров.

3.4 Chaos Engineering for Agents

Более продвинутая техника: хаотично вбрасывать сбои в симуляцию (например, отключать один из трёх эмулируемых микросервисов), чтобы проверить, как агент адаптируется. Это chaos testing в миниатюре.


4. Преимущества simulation testing (таблица)

ПреимуществоОписание
ЭкономияНет затрат на реальные API и инфраструктуру
ДетерминизмОдин и тот же тест всегда даёт одинаковый результат
Полнота покрытияМожно тестировать редкие сценарии: ошибки авторизации, пустые ответы, лимиты
БезопасностьАгент не может навредить production или оставить следы
СкоростьСимуляция работает быстрее реальных вызовов (нет сетевых задержек)
ПараллелизмДесятки тестов можно запускать одновременно без конфликтов

5. Недостатки и ограничения

  • Неполное соответствие реальности — симулятор всегда проще реального сервиса, поэтому поведение может отличаться.
    Решение: периодически запускать интеграционные тесты против реального окружения (smoke tests).
  • Сложность поддержки — при изменении API внешнего сервиса нужно обновлять mock’и.
    Решение: автоматическая генерация mock’ов на основе OpenAPI-спецификаций.
  • Ложная уверенность — если mock неверный, тест пройдёт, а в production упадёт.
    Решение: регулярно сверять mock с реальными ответами (contract testing).

6. Инструменты для simulation testing

ИнструментНазначениеЯзык
WireMockMock HTTP APIJava, .NET
MotoMock AWS-сервисовPython
LocalStackПолноценная эмуляция AWS в DockerPython / любой
responses / httprettyMock HTTP-запросов в PythonPython
TestcontainersЗапуск реальных БД в Docker для тестовJava, Python, Go
VCR.pyЗапись реальных запросов и воспроизведение из кассетPython
Mockito / unittest.mockОбщее мокированиеJava, Python

7. Интеграция simulation testing в CI/CD

Чтобы тесты агента были стабильными, их запускают в CI-пайплайне (например, GitHub Actions). Симулированная среда разворачивается прямо на раннере:

# .github/workflows/test_agent.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install dependencies
        run: pip install -r requirements.txt
      - name: Run simulation tests
        run: pytest tests/simulation/

Важно: симуляция не должна зависеть от внешних ресурсов (интернета). Все mock’и должны быть встроены в код или в Docker-контейнер.


8. Связь с другими видами тестирования

Тип тестированияОбъектЗависимость от внешних системПример
Unit testОтдельная функция агента (решение)Нет (все зависимые мокируются)Проверка логики выбора действия
Simulation testЦепочка действий агента (вызовы API)Заменены mock’амиПроверка обработки ошибки 500
Integration testАгент + несколько реальных компонентовЧастично реальные (тестовая БД)Проверка записи в тестовую БД
E2E testПолный pipeline (агент + production-заглушка)Отдельный тестовый стендПроверка сквозного сценария

Simulation testing занимает промежуточное место: он шире unit-тестов, но быстрее и дешевле полноценного integration.


9. Метрики качества simulation testing

Какие показатели можно измерять:

  • Coverage of API errors — сколько различных HTTP-кодов ошибок протестировано.
  • Determinism rate — доля тестов, которые дают одинаковый результат при повторном запуске (должно быть 100%).
  • Time per test — среднее время выполнения одного simulation-теста (обычно <1 с).
  • False positive rate — как часто тест проходит, но в production агент падает (вычисляется при ручной верификации).

10. Пример: simulation testing для AI-агента заказа пиццы

Сценарий: Агент принимает заказ, проверяет доступные ингредиенты, списывает счёт, отправляет в кухню.

# test_pizza_agent.py
import pytest
from pizza_agent import OrderAgent

def test_successful_order():
    # Mock: сервис ингредиентов всегда отвечает "есть всё"
    mock_inventory = {"pepperoni": 10, "cheese": 20}
    # Mock: платёжный шлюз возвращает success
    mock_payment = {"status": "paid", "tx_id": "tx_123"}

    agent = OrderAgent(
        inventory_url="http://mock-inventory",
        payment_url="http://mock-payment"
    )
    result = agent.process_order({"pizza": "pepperoni", "size": "large"})
    assert result["status"] == "confirmed"
    assert result["tx_id"] == "tx_123"

def test_inventory_out_of_stock():
    # Mock: нет пепперони
    mock_inventory = {"pepperoni": 0, "cheese": 20}
    agent = OrderAgent(inventory_url="http://mock-inventory")
    result = agent.process_order({"pizza": "pepperoni", "size": "large"})
    assert result["status"] == "failed"
    assert "out_of_stock" in result["reason"]

Пет-проект для закрепления

Задача: Разработать simulation-тесты для Telegram-агента, который принимает команды и вызывает открытое API (погода, курсы валют, перевод текста).

Инструменты: Python, python-telegram-bot, responses, pytest, unittest.mock.

Шаги:

  1. Напишите простого агента, который по команде /weather Москва вызывает OpenWeatherMap API и возвращает температуру.
  2. Подготовьте mock OpenWeatherMap с помощью responses: верните фиксированный JSON.
  3. Напишите тесты:
    • Команда /weather без города → агент запрашивает город.
    • Успешный ответ с корректной температурой.
    • Ошибка API (500) → агент отвечает «Попробуйте позже».
    • Таймаут запроса → агент повторяет попытку через 1 с (retry logic).
  4. Убедитесь, что все тесты выполняются без интернета и детерминированно.
  5. Добавьте пару fault injection тестов: медленный ответ (latency 10 с) → проверьте, не превышен ли таймаут агента.

Ожидаемый результат: Пакет тестов (минимум 5), который можно запустить в CI за 2 секунды, покрывающий основные сценарии и ошибки внешнего API.


Связь с другими вопросами

ВопросТема
780Как тестировать AI-агентов?
782CI/CD для агентов
785Observability и мониторинг агентов
787Оценка качества работы агента (evaluation)
789Что такое agent sandboxing?
791Contract testing для агентских систем

Навигация