English translation is not available yet. Showing Russian content.
Что такое «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
| Инструмент | Назначение | Язык |
|---|---|---|
| WireMock | Mock HTTP API | Java, .NET |
| Moto | Mock AWS-сервисов | Python |
| LocalStack | Полноценная эмуляция AWS в Docker | Python / любой |
| responses / httpretty | Mock HTTP-запросов в Python | Python |
| 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.
Шаги:
- Напишите простого агента, который по команде
/weather Москвавызывает OpenWeatherMap API и возвращает температуру. - Подготовьте mock OpenWeatherMap с помощью responses: верните фиксированный JSON.
- Напишите тесты:
- Команда
/weatherбез города → агент запрашивает город. - Успешный ответ с корректной температурой.
- Ошибка API (500) → агент отвечает «Попробуйте позже».
- Таймаут запроса → агент повторяет попытку через 1 с (retry logic).
- Команда
- Убедитесь, что все тесты выполняются без интернета и детерминированно.
- Добавьте пару fault injection тестов: медленный ответ (latency 10 с) → проверьте, не превышен ли таймаут агента.
Ожидаемый результат: Пакет тестов (минимум 5), который можно запустить в CI за 2 секунды, покрывающий основные сценарии и ошибки внешнего API.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 780 | Как тестировать AI-агентов? |
| 782 | CI/CD для агентов |
| 785 | Observability и мониторинг агентов |
| 787 | Оценка качества работы агента (evaluation) |
| 789 | Что такое agent sandboxing? |
| 791 | Contract testing для агентских систем |
Навигация
- Предыдущий: 787
- Следующий: 789
- Индекс: 00. Индекс разборов