Стратегии подачи контекста
Updated Jul 2026
Основная проблема: LLM хороши лишь настолько, насколько хорош их ввод
LLM, генерирующая тесты без контекста, -- это как QA-инженер, пишущий тесты, не читая требований. Результат может выглядеть синтаксически корректным, но он упустит доменные ограничения, использует неправильные имена методов и сгаллюцинирует несуществующие API.
Искусство подачи контекста заключается в том, чтобы решить, что включать, сколько включать и в каком порядке -- учитывая, что каждый токен контекста стоит денег и конкурирует за место в окне внимания модели.
Иерархия контекста
Не весь контекст одинаково ценен. Когда бюджет токенов ограничен, расставляйте приоритеты безжалостно:
Priority 1: The actual specification (OpenAPI schema, AC, Figma annotations)
Priority 2: Existing test patterns in the codebase (so AI matches style)
Priority 3: Domain constraints (business rules not in the spec)
Priority 4: Technical stack details (frameworks, helpers, fixtures)
Priority 5: Examples of good vs bad tests from prior reviews
Почему именно такой порядок? Приоритет 1 предотвращает галлюцинации (ИИ тестирует то, что реально существует). Приоритет 2 предотвращает расхождение стилей (ИИ пишет тесты, которые ваша команда узнает). Приоритет 3 ловит бизнес-логику, которую спецификации часто упускают. Приоритет 4 обеспечивает компилируемость кода. Приоритет 5 -- это бонус, улучшающий качество со временем.
Что подавать и как
| Источник | Как подавать | Почему это важно |
|---|---|---|
| OpenAPI/Swagger-спецификация | Вставьте релевантный JSON/YAML эндпоинта напрямую | Точные имена полей, типы, ограничения -- устраняет догадки |
| Пользовательская история + критерии приёмки | Скопируйте из Jira/Linear дословно | Сохраняет первоначальный замысел, граничные случаи, упомянутые в комментариях |
| Существующий тестовый файл | Вставьте 2-3 репрезентативных теста как «руководство по стилю» | ИИ копирует именование, структуру, стиль утверждений, фикстуры |
| Схема базы данных | Вставьте операторы CREATE TABLE | Выявляет ограничения, которые ИИ может протестировать (NOT NULL, UNIQUE, FK, CHECK) |
| Документация кодов ошибок | Вставьте каталог ошибок | ИИ генерирует тесты, вызывающие каждую задокументированную ошибку |
| UI-макет/Figma | Опишите макет или используйте скриншот + модель с компьютерным зрением | Генерирует тесты доступности и тесты макета |
| Конфигурация CI | Вставьте релевантные команды запуска тестов | ИИ понимает, как будут запускаться тесты (параллельно, флаги покрытия) |
Подача OpenAPI-схемы
Here is the OpenAPI schema for the endpoint under test:
```yaml
paths:
/api/v2/orders:
post:
summary: Create a new order
security:
- BearerAuth: [customer]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrder'
responses:
'201':
description: Order created
'400':
description: Validation error
'401':
description: Unauthorized
'409':
description: Duplicate order (idempotency key conflict)
components:
schemas:
CreateOrder:
type: object
required: [items, shipping_address, idempotency_key]
properties:
items:
type: array
minItems: 1
maxItems: 50
items:
type: object
required: [product_id, quantity]
properties:
product_id:
type: string
format: uuid
quantity:
type: integer
minimum: 1
maximum: 100
shipping_address:
$ref: '#/components/schemas/Address'
idempotency_key:
type: string
format: uuid
coupon_code:
type: string
pattern: "^[A-Z0-9]{8}$"
Обратите внимание, что каждое ограничение в схеме (minItems, maxItems, minimum, maximum, pattern, format) -- это тестовый сценарий, ожидающий генерации. LLM видит эти ограничения и автоматически создаёт тесты граничных значений.
Подача существующих тестов как руководства по стилю
Here are two existing tests from our codebase. Match their style exactly:
```python
class TestOrderCreation:
"""Tests for POST /api/v2/orders endpoint."""
def test_should_create_order_when_valid_payload(
self, api_client, auth_headers, product_factory
):
# Arrange
product = product_factory.create()
payload = {
"items": [{"product_id": str(product.id), "quantity": 2}],
"shipping_address": VALID_ADDRESS,
"idempotency_key": str(uuid4()),
}
# Act
response = api_client.post(
"/api/v2/orders", json=payload, headers=auth_headers
)
# Assert
assert response.status_code == 201
order = response.json()
assert order["status"] == "pending"
assert len(order["items"]) == 1
assert order["items"][0]["quantity"] == 2
def test_should_reject_order_when_empty_items_list(
self, api_client, auth_headers
):
# Arrange
payload = {
"items": [],
"shipping_address": VALID_ADDRESS,
"idempotency_key": str(uuid4()),
}
# Act
response = api_client.post(
"/api/v2/orders", json=payload, headers=auth_headers
)
# Assert
assert response.status_code == 400
assert "items" in response.json()["detail"].lower()
Показывая два теста -- один happy-path, один с ошибкой валидации -- ИИ узнаёт:
- Структуру класса с docstring-ами
- Внедрение зависимостей на основе фикстур (
api_client,auth_headers,product_factory) - Соглашение об именовании:
test_should_X_when_Y - Маркеры комментариев для Arrange/Act/Assert
- Стиль утверждений (код статуса + проверки конкретных полей)
- Использование константы
VALID_ADDRESSиuuid4()
Антипаттерн: свалка контекста
Не вставляйте всю вашу кодовую базу в промпт. Качество LLM снижается при наличии нерелевантного контекста. Сфокусированный фрагмент в 200 строк даёт лучшие тесты, чем свалка в 5000 строк.
Это называется проблема иголки в стоге сена -- чем больше сена, тем сложнее LLM найти иголку. Исследования 2024-2025 годов последовательно показывают, что модели работают лучше всего, когда релевантный контекст размещён в начале или конце промпта, а производительность снижается при большом объёме нерелевантного содержимого в середине.
Симптомы перегрузки контекстом
- Сгенерированные тесты ссылаются на функции из неправильного файла
- Тесты смешивают стили из разных частей кодовой базы
- LLM «забывает» ограничения, упомянутые в начале промпта
- Вывод короче и менее детализирован, чем ожидалось (модель исчерпала токены вывода, обрабатывая раздутый ввод)
Решение: оконный подход к контексту
Вместо того чтобы сбрасывать всё, используйте подход контекстного окна:
Step 1: Feed the spec (Priority 1) -- generate initial tests
Step 2: Review output -- identify style mismatches
Step 3: Feed 2-3 existing tests as style examples (Priority 2) -- regenerate
Step 4: Review output -- identify missing domain rules
Step 5: Add domain constraints (Priority 3) -- regenerate specific tests
Этот итеративный подход держит каждый промпт сфокусированным и даёт лучшие результаты, чем один массивный промпт.
Продвинутая стратегия: сжатие контекста
Когда необходимо включить большой объём контекста, сжимайте его. Вместо того чтобы вставлять исходный файл в 500 строк, сделайте резюме:
The UserService class has these public methods:
- create_user(dto: CreateUserDTO) -> User — validates email uniqueness, hashes password
- get_user(id: UUID) -> User — raises NotFoundError if missing
- update_user(id: UUID, dto: UpdateUserDTO) -> User — partial update, re-validates email if changed
- delete_user(id: UUID) -> None — soft delete (sets deleted_at timestamp)
Key constraints:
- Email must be unique (case-insensitive)
- Password minimum 8 chars, must include a number
- Soft-deleted users cannot log in but their data is retained for 30 days
Это 10-строчное резюме несёт ту же информацию, что и 200-строчный исходный файл, с точки зрения генерации тестов.
Стратегия: многоходовое построение контекста
Для сложных функциональностей выстраивайте контекст через несколько промптов в диалоге:
Turn 1: "Here is the OpenAPI schema for the payments endpoint. Summarize the
test scenarios you would create."
Turn 2: "Good. Here are our existing payment tests for reference style.
Now generate the first 10 tests matching this style."
Turn 3: "These look good. Now add tests for the edge cases: expired cards,
insufficient funds, and currency conversion rounding."
Turn 4: "Review all generated tests. Which ones are testing the mock
instead of the real behavior? Flag any tautology tests."
Каждый ход добавляет контекст инкрементально, а история диалога предоставляет неявный контекст из предыдущих ходов. Это эффективнее одного массивного промпта, потому что:
- Внимание LLM сфокусировано на одной задаче за раз
- Вы можете корректировать курс между ходами
- Вы выстраиваете рабочий процесс с ревью на каждом шаге
Чек-лист подачи контекста
Перед отправкой промпта для генерации тестов проверьте:
[ ] Specification artifact is included (schema, AC, or story)
[ ] Only relevant portions are included (not the entire file)
[ ] Existing test examples are provided for style matching
[ ] Business rules not in the spec are stated explicitly
[ ] Framework and language are specified
[ ] Auth mechanism and test helpers are named exactly
[ ] Output format expectations are clear
[ ] Token budget is reasonable (< 8K input for focused generation)
Ключевой вывод
Подача контекста -- это навык с наибольшим рычагом воздействия в проектировании тестов с ИИ. Правильные 200 строк контекста дают лучшие тесты, чем свалка в 5000 строк. Отдавайте приоритет спецификациям перед кодом, подавайте инкрементально, а не всё сразу, и всегда включайте примеры стиля из вашего существующего набора тестов.