AI-автогенерація інтеграційних тестів
Інтеграційні тести перевіряють взаємодію компонентів: сервіс A викликає сервіс B, результат пишеться в базу, подія йде в чергу. Написати такі тести складніше, ніж unit — треба розуміти граф залежностей, налаштувати тестові середовища, розставити fixtures. AI-генератор аналізує архітектуру сервісів, схему бази даних та OpenAPI-специфікації, створюючи тести для критичних інтеграційних шляхів.
Аналіз залежностей і генерація тестів
from langchain_openai import ChatOpenAI
import json
from pathlib import Path
import yaml
class IntegrationTestGenerator:
INTEGRATION_PROMPT = """Створи інтеграційний тест для взаємодії компонентів.
Компоненти та їх контракти:
{components}
Схема бази даних:
{db_schema}
Інтеграційний сценарій:
{scenario}
Вимоги:
- pytest + SQLAlchemy для роботи з БД (використовуй транзакції з rollback)
- httpx.AsyncClient для HTTP-викликів
- pytest-asyncio для async тестів
- Тестова база даних через pytest fixture (не боєва!)
- Перевіряй не тільки HTTP-статус, а й стан у БД після операції
- Використовуй factory_boy або pytest-factoryboy для тестових даних
Повернення повного коду тесту з fixtures."""
def __init__(self):
self.llm = ChatOpenAI(model="gpt-4o", temperature=0.1)
def generate_db_integration_tests(
self,
model_code: str,
repository_code: str,
db_schema: str
) -> str:
prompt = f"""Створи pytest інтеграційні тести для Repository та Model.
SQLAlchemy Model:
```python
{model_code}
Repository:
{repository_code}
DDL схема:
{db_schema}
Створи тести:
- CRUD операції (create, read, update, delete)
- Фільтрація та сортування
- Транзакції (успішний commit, rollback при помилці)
- Унікальні обмеження (спроба вставити дублікат)
- Foreign key constraints
- Пагінація (якщо є в Repository)
Fixtures:
- db_session: SQLAlchemy session з rollback після кожного тесту
- test_data factories через factory_boy
Повернення коду тестів.""" return self.llm.invoke(prompt).content
def generate_service_integration_tests(
self,
service_a_spec: dict,
service_b_spec: dict,
interaction_patterns: list[str]
) -> str:
"""Генерує тести для взаємодії між сервісами"""
prompt = f"""Створи pytest інтеграційні тести для взаємодії сервісів.
Сервіс A (клієнт):
- Base URL: {service_a_spec['base_url']}
- Викликає: {json.dumps(service_a_spec['calls'], ensure_ascii=False)}
Сервіс B (сервер):
- Endpoints: {json.dumps(service_b_spec.get('endpoints', []), ensure_ascii=False)}
Паттерни взаємодії: {chr(10).join(f"- {p}" for p in interaction_patterns)}
Використовуй:
- pytest + respx для мокування HTTP-відповідей сервісу B
- Тести на retry-логіку (що відбувається при таймауті сервісу B)
- Тести на circuit breaker (якщо є)
- Тести на коректну обробку 4xx/5xx від сервісу B
Повернення коду тестів з fixtures.""" return self.llm.invoke(prompt).content
### Генерація fixtures та тестових даних
```python
class TestDataGenerator:
FACTORY_PROMPT = """Створи factory_boy factories для моделей.
SQLAlchemy моделі:
{models_code}
Створи:
1. Factory для кожної моделі
2. SubFactory для пов'язаних об'єктів
3. Trait для специфічних станів (напр. expired_user, admin_user)
4. Batch-створення через factory.build_batch
Повернення коду factories."""
async def generate_factories(self, models_code: str) -> str:
result = await self.llm.ainvoke(
self.FACTORY_PROMPT.format(models_code=models_code)
)
return result.content
async def generate_fixtures_from_schema(self, schema: dict) -> str:
"""Створює pytest fixtures з схеми БД"""
prompt = f"""Створи pytest fixtures для тестової бази даних.
Схема: {json.dumps(schema, ensure_ascii=False, indent=2)}
Fixtures потрібні:
- engine: SQLAlchemy engine до test DB (PostgreSQL через pytest-postgresql)
- db_session: сесія з rollback після кожного тесту
- Fixtures для кожної таблиці: мінімальний валідний об'єкт
- seeded_db: база з початковими даними для e2e тестів
Використовуй scope='function' для db_session, scope='session' для engine.
Повернення Python коду."""
return (await self.llm.ainvoke(prompt)).content
Тести для черг повідомлень
QUEUE_INTEGRATION_PROMPT = """Створи тест для інтеграції з чергою повідомлень.
Producer-код:
{producer_code}
Consumer-код:
{consumer_code}
Використовуй:
- pytest + testcontainers-python (RabbitMQ/Kafka у Docker)
- Перевіряй: повідомлення відправлено → оброблено → результат у БД
- Тест на dead letter queue (повідомлення не оброблено → DLQ)
- Тест на ідемпотентність (повторна обробка того ж повідомлення)
- Тайм-аут очікування обробки: asyncio.wait_for з timeout=10
Повернення повного коду тесту."""
Кейс: e-commerce платформа, 15 мікросервісів. Проблема: інтеграційне тестування робилось вручну перед кожним релізом (2 QA × 3 дні). Сгенерували 180 інтеграційних тестів для критичних шляхів: замовлення → оплата → уведомлення → оновлення складу. З 180 тестів при першому запуску впало 23 — знайшли реальні баги в обробці currency conversion, дублюванні подій у черзі, неправильному статусі при partial payment.
Строки: інтеграційні тести для БД + сервісів: 3–5 тижнів; з чергами та повним окруженням через testcontainers: 5–7 тижнів.







