AI-автогенерация тест-сценариев
Тест-сценарий — это не тест. Это описание ситуации, которую нужно протестировать: пользователь, действие, условия, ожидаемый результат. Написание тест-сценариев из требований — монотонная работа, которая при дефиците времени делается наспех или не делается вообще. AI-генератор создаёт тест-сценарии из user stories, спецификаций и ER-диаграмм, покрывая позитивные пути, негативные кейсы и граничные условия.
Генерация из user stories
from langchain_openai import ChatOpenAI
from pydantic import BaseModel
from typing import Optional
import json
class TestScenario(BaseModel):
id: str
title: str
type: str # positive / negative / boundary / edge_case
priority: str # P1 / P2 / P3
preconditions: list[str]
steps: list[str]
expected_result: str
tags: list[str]
related_requirement: str
class TestScenarioGenerator:
GENERATION_PROMPT = """Ты — опытный QA-инженер. Создай тест-сценарии из требования.
Требование: {requirement}
Acceptance Criteria:
{acceptance_criteria}
Создай тест-сценарии трёх типов:
1. **Позитивные** (happy path + основные варианты)
2. **Негативные** (невалидные данные, запрещённые операции)
3. **Граничные** (минимальные/максимальные значения, пустые данные)
Для каждого сценария:
- Заголовок (действие + условие)
- Предусловия
- Шаги (конкретные, не "нажми кнопку", а "нажми кнопку 'Сохранить' в форме регистрации")
- Ожидаемый результат (измеримый)
- Приоритет (P1 — критичный бизнес-флоу, P2 — важный, P3 — второстепенный)
Верни JSON-массив TestScenario."""
def __init__(self):
self.llm = ChatOpenAI(model="gpt-4o", temperature=0.2)
def generate_from_user_story(
self,
user_story: str,
acceptance_criteria: list[str],
domain_context: str = ""
) -> list[TestScenario]:
ac_text = "\n".join([f"- {ac}" for ac in acceptance_criteria])
prompt = self.GENERATION_PROMPT.format(
requirement=user_story + ("\n\nКонтекст домена: " + domain_context if domain_context else ""),
acceptance_criteria=ac_text
)
response = self.llm.invoke(prompt)
scenarios_data = json.loads(response.content)
return [TestScenario(**s) for s in scenarios_data]
def generate_from_api_spec(self, openapi_spec: dict) -> list[TestScenario]:
"""Генерирует сценарии из OpenAPI спецификации"""
scenarios = []
for path, methods in openapi_spec.get("paths", {}).items():
for method, spec in methods.items():
endpoint_scenarios = self._generate_endpoint_scenarios(
path, method, spec
)
scenarios.extend(endpoint_scenarios)
return scenarios
def _generate_endpoint_scenarios(
self,
path: str,
method: str,
spec: dict
) -> list[TestScenario]:
prompt = f"""Создай тест-сценарии для API endpoint.
Endpoint: {method.upper()} {path}
Описание: {spec.get('summary', '')}
Параметры: {json.dumps(spec.get('parameters', []), ensure_ascii=False, indent=2)}
Request body: {json.dumps(spec.get('requestBody', {}), ensure_ascii=False, indent=2)}
Responses: {json.dumps(spec.get('responses', {}), ensure_ascii=False, indent=2)}
Сценарии:
- 200 (success) с валидными данными
- 400 (bad request) — невалидные параметры
- 401/403 — авторизация
- 404 — ресурс не найден
- Граничные значения для числовых параметров
- Специфичные для данного endpoint (на основе описания)
Верни JSON-массив тест-сценариев."""
response = self.llm.invoke(prompt)
return json.loads(response.content)
Интеграция с Jira + TestRail
from jira import JIRA
import testrail
class TestScenarioSync:
def push_to_testrail(
self,
scenarios: list[TestScenario],
project_id: int,
suite_id: int
):
"""Публикует сценарии в TestRail"""
client = testrail.APIClient(TESTRAIL_URL)
client.user = TESTRAIL_USER
client.password = TESTRAIL_KEY
for scenario in scenarios:
client.send_post(
f'add_case/{suite_id}',
{
'title': scenario.title,
'type_id': self._get_type_id(scenario.type),
'priority_id': self._get_priority_id(scenario.priority),
'custom_preconds': '\n'.join(scenario.preconditions),
'custom_steps': '\n'.join([
f"{i+1}. {step}"
for i, step in enumerate(scenario.steps)
]),
'custom_expected': scenario.expected_result,
'refs': scenario.related_requirement
}
)
def pull_from_jira_and_generate(
self,
jira_client: JIRA,
sprint_id: str
) -> list[TestScenario]:
"""Получает user stories из спринта и генерирует сценарии"""
issues = jira_client.search_issues(
f'sprint = {sprint_id} AND issuetype = Story AND status != Done'
)
all_scenarios = []
for issue in issues:
scenarios = self.generator.generate_from_user_story(
user_story=issue.fields.summary,
acceptance_criteria=self._extract_ac(issue.fields.description),
)
all_scenarios.extend(scenarios)
return all_scenarios
Матрица покрытия требований
def build_coverage_matrix(
requirements: list[dict],
scenarios: list[TestScenario]
) -> dict:
"""Строит матрицу трассируемости требований → сценарии"""
matrix = {}
for req in requirements:
req_id = req["id"]
covered_scenarios = [
s for s in scenarios
if s.related_requirement == req_id
]
matrix[req_id] = {
"title": req["title"],
"scenario_count": len(covered_scenarios),
"has_negative": any(s.type == "negative" for s in covered_scenarios),
"has_boundary": any(s.type == "boundary" for s in covered_scenarios),
"coverage_grade": "full" if len(covered_scenarios) >= 3 else "partial" if covered_scenarios else "none"
}
return matrix
Кейс: ERP-система, 200+ user stories на квартал. QA-команда (4 человека) не успевала писать сценарии до начала спринта — тест-планирование шло в параллель с разработкой. После внедрения AI-генератора: 200 user stories → 1100 тест-сценариев за 2 часа (включая проверку). Время QA на написание сценариев: 3 дня → 4 часа (ревью и коррекция). P1-сценарии покрыты на 100% перед стартом разработки.
Сроки: генератор из user stories + интеграция с Jira: 2–3 недели; с TestRail/Xray и матрицей трассируемости: 4–5 недель.







