中文翻译暂不可用,显示俄语原文。
Написать тесты для меж-агентской коммуникации
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Написать тесты для меж-агентской коммуникации
1. Цель задачи
Протестировать протокол обмена сообщениями между AI-агентами в многомодульной системе. Создать мокированную шину сообщений (mock message bus), которая эмулирует реальный брокер (например, RabbitMQ или Kafka), и написать набор тестов, проверяющих корректность формата, маршрутизации, обработки ошибок и восстановления после сбоев. Достичь покрытия кода модуля коммуникации не менее 95% (branch coverage + line coverage).
Ключевой результат Набор автоматизированных тестов (Python + pytest), которые запускаются единой командой и подтверждают, что протокол меж-агентской коммуникации работает корректно во всех штатных и аварийных сценариях.
2. Исходные данные
Перед началом необходимо иметь или создать:
| Что нужно | Откуда взять |
|---|---|
| Описание протокола сообщений (формат, типы, маршруты, обязательные поля) | Прилагается к задаче (см. ниже) |
| Агенты-заглушки (sender / receiver), реализующие базовый интерфейс | Написать самостоятельно или взять готовый шаблон |
Исходный код модуля agent_comm (классы MessageBus, Agent, Message) | Предоставлен репозиторием задания (входной код для тестирования) |
| Инструмент для измерения покрытия | Установить pytest-cov или coverage.py |
Если нет реального модуля agent_comm — симулируем:
- Создать пакет
agent_commсо следующей структурой:agent_comm/ ├── __init__.py ├── message.py # класс Message (dict с полями: id, sender, receiver, type, payload, timestamp) ├── bus.py # класс MessageBus (регистрация агентов, отправка, подписка) ├── agent.py # абстрактный Agent (методы on_message, send) └── exceptions.py # кастомные исключения (MessageFormatError, TimeoutError, BusFull) - Реализовать
MessageBusна основе очередей asyncio.Queue или обычных списков (для синхронного варианта). - Включить хотя бы один реальный сценарий: агент отправляет сообщение другому, агент подписывается на топик, шина проверяет обязательные поля.
- Предоставить этот код исполнителю задачи.
Дополнительные ресурсы
- Протокол: JSON-сообщение с полями
id(UUID), sender, receiver,type(строка), payload (словарь), timestamp (ISO 8601). Валидация через Pydantic-модели. - Шина поддерживает: send (точка-точка), publish (топик), subscribe, unsubscribe, гарантии exactly-once (имитация).
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык программирования | Python 3.11+ | Реализация агентов и шины |
| Тестирование | pytest 8.x, pytest-asyncio | Запуск unit- и integration-тестов |
| Моки | unittest.mock / pytest-mock | Замена внешних зависимостей (брокер, логгер) |
| Покрытие | pytest-cov (coverage.py) | Измерение line + branch coverage |
| Валидация сообщений | pydantic v2 | Проверка формата сообщений |
| Асинхронность | asyncio | Эмуляция реальной асинхронной шины |
| Линтер/форматтер | ruff | Поддержание стандарта кода |
4. Этапы выполнения
Этап 1: Изучение спецификации и подготовка фикстур (оценка 30 мин)
Действия
- Прочитать описание протокола и интерфейс классов в модуле
agent_comm. - Определить, какие тесты необходимы (см. критерии приемки).
- Создать файл
tests/test_message_bus.pyи фикстуруmessage_bus:@pytest.fixture def message_bus(): return MessageBus() - Создать фикстуру
sample_messageдля генерации тестового сообщения. - Настроить pyproject.toml для включения branch coverage:
[tool.coverage.run] branch = true source = ["agent_comm"] [tool.coverage.report] show_missing = true
Ожидаемый результат этапа Готовый скелет тестового файла, фикстуры, корректная конфигурация coverage.
Этап 2: Написание тестов для базовой отправки/получения (оценка 1.5 ч)
Действия
- Написать тест
test_send_message:- регистрируем агента-получателя
receiver_agent - отправляем сообщение через message_bus.send(receiver_id, msg)
- проверяем, что получатель вызвал
on_messageс этим сообщением.
- регистрируем агента-получателя
- Написать тест
test_publish_subscribe:- два агента подписываются на один топик
- публикуем сообщение через message_bus.publish(topic, msg)
- оба агента должны получить сообщение.
- Написать тест
test_message_validation:- пытаемся отправить сообщение без обязательного поля
type - ожидаем MessageFormatError (или другое исключение).
- пытаемся отправить сообщение без обязательного поля
- Написать тест
test_unsubscribe:- подписываем агента, затем отписываем, публикуем — агент не должен получить сообщение.
- Написать тест
test_concurrent_send(если шина async):- создаём несколько агентов, отправляем одновременно, проверяем, что все сообщения доставлены без потерь.
- Для каждого теста использовать pytest-asyncio (если шина async) или обычный pytest.
Ожидаемый результат этапа Все основные сценарии отправки/получения покрыты тестами, уровень line coverage > 70%.
Этап 3: Тестирование обработки ошибок и граничных случаев (оценка 1 ч)
Действия
- Написать тест
test_send_to_nonexistent_agent:- отправка на несуществующий ID — ожидать исключение AgentNotFoundError.
- Написать тест
test_bus_full_capacity:- шина с ограничением на количество непрочитанных сообщений (например, 10)
- заполнить очередь сверх лимита — ожидать BusFullError.
- Написать тест
test_invalid_message_format: - Написать тест
test_duplicate_message_id:- шина не должна принимать сообщение с дублирующимся id (если есть политика idempotency).
- Написать тест
test_timeout:- если получатель не обработал сообщение за установленный таймаут, шина возвращает ошибку или повторяет попытку (зависит от реализации).
- Написать тест
test_shutdown_cleanup:- при вызове
message_bus.stop()все незавершённые сообщения корректно завершаются (проверить отсутствие утечек задач).
- при вызове
Ожидаемый результат этапа Coverage branch близок к 100% в модулях bus, exceptions, message (не менее 90%).
Этап 4: Интеграционное тестирование с мок-брокером (оценка 1 ч)
Действия
- Если модуль
agent_commиспользует внешний брокер (RabbitMQ/Kafka), замокать его с помощью unittest.mock.patch:Если внешнего брокера нет, пропустить этот этап (мок-шина уже тестируется).@patch('agent_comm.bus.RabbitMQConnection') def test_broker_connection_recovery(mock_connection): mock_connection.side_effect = ConnectionError() bus = MessageBus() # должно сработать повторное подключение bus.send(...) - Создать тест, проверяющий логирование (логгеры мокаются).
- Написать тест на долгое выполнение (stress test с 1000 сообщений) — с таймаутом, чтобы не нарушать CI.
- Проверить, что при ошибке сериализации сообщение не отправляется, а возвращается корректная ошибка.
Ожидаемый результат этапа Покрытие всех путей, включая соединения и логгирование.
Этап 5: Измерение покрытия и достижение 95% (оценка 30 мин)
Действия
- Запустить coverage:
pytest --cov=agent_comm --cov-branch --cov-report=html tests/ - Проанализировать отчёт
htmlcov/index.html, найти непокрытые строки и ветки. - Добавить тесты для непокрытых участков (например, редкие исключения, альтернативные ветки
if). - Повторять до достижения 95% branch coverage (минимально; target 95% с допуском 1%).
- Зафиксировать финальный отчёт в
coverage.xml.
Ожидаемый результат этапа Покрытие >= 95% (линии + ветви). Тесты проходят без ошибок.
5. Критерии приемки (Definition of Done)
- Все тесты запускаются одной командой
pytest tests/и проходят на 100%. - Покрытие кода модуля
agent_comm(branch + line) составляет не менее 95% согласноcoverage.py. - Включены тесты на: отправку point-to-point, publish/subscribe, unsubscription, валидацию обязательных полей.
- Включены тесты на обработку ошибок: несуществующий получатель, превышение ёмкости, неверный формат, дубликат ID, таймаут.
- Моки используются только для внешних зависимостей (брокер, логгер); внутренняя логика тестируется на реальных объектах.
- Каждый тест атомарен, не зависит от других, использует уникальные фикстуры.
- Генерация отчёта о покрытии в формате HTML и XML.
- Код тестов оформлен по PEP 8, одобрен линтером
ruff. - Документация: README с командами запуска и описанием структуры тестов.
6. Ожидаемый результат
Основной артефакт Папка tests/ с тестами и конфигурацией.
Содержание файлов
tests/__init__.py(пустой)tests/test_message_bus.py— основные тесты.tests/conftest.py— фикстуры (message_bus,sample_message,agent_stub).pyproject.toml(или.coveragerc) с настройками coverage.README.mdс инструкцией по запуску.- (опционально)
tests/test_errors.py,tests/test_integration.pyдля разделения.
Дополнительные результаты
- Отчёт coverage в
htmlcov/index.html(если не включено в gitignore). - Линтер
ruff check .не выводит ошибок.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Асинхронные тесты зависают при ошибках | Использовать pytest-asyncio с таймаутом: @pytest.mark.timeout(2); для каждого асинхронного теста добавить pytestmark = pytest.mark.asyncio |
| Невозможно измерить branch coverage для исключений, которые сложно вызвать | Написать тест с некорректным типом данных, передаваемым в метод; использовать pytest.raises и проверить, что ошибка логируется |
| Пересечение состояний между тестами (shared state в MessageBus) | Каждая фикстура создаёт новый экземпляр шины; моки очищаются в autouse фикстуре |
| Большое количество тестов замедляет CI | Разделить на slow/fast маркеры; slow-тесты запускать отдельно |
Покрытие падает из-за недостижимого кода (например, # pragma: no cover) | Разрешить исключать такие строки в .coveragerc с комментарием; убедиться, что это действительно недостижимо |
8. Бюджет времени (оценка)
| Этап | Описание | Время |
|---|---|---|
| 1 | Изучение спецификации, настройка фикстур | 30 мин |
| 2 | Тесты базовой отправки/получения | 1 ч 30 мин |
| 3 | Тесты обработки ошибок и граничных случаев | 1 ч |
| 4 | Интеграционное тестирование с моками | 1 ч |
| 5 | Анализ coverage и доведение до 95% | 30 мин |
| Итого | 4 ч 30 мин |
Примечание Для первого раза (изучение асинхронного тестирования, моков) добавьте 1.5 часа на раскачку.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 12 | Настройка pytest для асинхронных тестов |
| 35 | Создание фикстур в pytest |
| 78 | Измерение branch coverage в coverage.py |
| 120 | Mock объектов в unittest.mock |
| 156 | Проектирование протокола меж-агентской коммуникации |
| 189 | Тестирование edge-кейсов с сообщениями |
| 210 | Организация тестов для микросервисов |
| 340 | Использование pydantic для валидации сообщений |
| 415 | Параметризованные тесты в pytest |
| 520 | Асинхронные очереди asyncio и их тестирование |
10. Чек-лист самопроверки
- Я создал структуру
tests/и настроил coverage вpyproject.toml? - Все тесты запускаются, зелёные, и покрытие действительно >=95%?
- Я проверил, что каждый тест атомарен и не полагается на порядок выполнения?
- Я написал хотя бы один тест для каждого исключения, описанного в
exceptions.py? - Отчёт coverage не содержит неожиданно низких показателей в ключевых методах (
send,publish,subscribe,_validate)?