AI-система тестування та QA програмного забезпечення
Ваш coverage-звіт показує 90% рядків, але production-баги все одно прослизають. Чому? Тому що line coverage не враховує бізнес-сценарії, граничні значення та інтеграційні стики. AI-система QA вирішує цю проблему, аналізуючи AST, вимоги з Jira та мутаційне тестування. Результат: покриття граничних кейсів зростає з 30% до 95%. Понад 5 років ми впроваджували такі системи для 50+ проєктів — від стартапів до enterprise. Середня економія на QA-команді після впровадження становить 40–60%, а кількість production-інцидентів знижується на 50–70% за перші три місяці. Оцінимо ваш проєкт за один день — просто зв'яжіться з нами. Замовте попередній аналіз і дізнайтеся, скільки багів ховається у вашому коді.
Проблеми, які вирішуємо
- Хибне відчуття безпеки. 100% line coverage не гарантує, що протестовані всі бізнес-сценарії. AI знаходить логічні пропуски.
- Крихкість тестів. При рефакторингу тести ламаються — AI-самовідновлення адаптує їх під нову архітектуру.
- Сліпі зони інтеграцій. Модульні тести не бачать помилки на стиках компонентів. AI генерує інтеграційні тести на основі графа викликів.
- Витрати ручної праці. Тестувальник витрачає до 60% часу на рутину — AI бере на себе генерацію базових та граничних кейсів.
Компоненти AI-системи тестування
[Code Analysis] [Requirement Analysis]
AST парсинг NLP з Jira/Confluence
↓ ↓
[Test Generation Engine]
Unit | Integration | E2E | API
↓
[Test Prioritization]
Change Impact Analysis → запускати потрібні тести, не всі
↓
[Result Analysis]
Failure Classification + Root Cause Suggestion
↓
[Coverage Intelligence]
Семантичні прогалини в покритті
Кожен компонент — окремий мікросервіс, що спілкується через RabbitMQ. Це дозволяє незалежно масштабувати генерацію та аналіз.
Як AI знаходить семантичні прогалини в покритті?
Традиційний coverage (Istanbul, JaCoCo) рахує рядки. Проблема: 100% line coverage не означає, що протестовані всі бізнес-сценарії. Наш SemanticCoverageAnalyzer використовує GPT-4o з температурою 0.1 для детекції пропусків:
from langchain_openai import ChatOpenAI
import ast
import textwrap
class SemanticCoverageAnalyzer:
"""Аналізує семантичні прогалини в тестовому покритті"""
ANALYSIS_PROMPT = """Проаналізуй функцію та існуючі тести.
Визнач, які бізнес-сценарії та граничні умови НЕ покриті.
Функція:
```python
{function_code}
Існуючі тести:
{existing_tests}
Визнач непокриті сценарії:
- Граничні значення (empty string, None, 0, max int, negative)
- Комбінації параметрів
- Сценарії помилок (exceptions, invalid input)
- Конкурентні доступи (якщо застосовно)
- Бізнес-правила в умовах
Для кожного: опиши сценарій + чому він важливий + можливий баг, якщо не тестувати. Поверни JSON: {{gaps: [{{scenario, importance, potential_bug}}]}}"""
def __init__(self):
self.llm = ChatOpenAI(model="gpt-4o", temperature=0.1)
def analyze_function_coverage(
self,
function_source: str,
test_source: str
) -> list[dict]:
result = self.llm.invoke(
self.ANALYSIS_PROMPT.format(
function_code=function_source,
existing_tests=test_source
)
)
import json
return json.loads(result.content)["gaps"]
def extract_functions_from_module(self, source: str) -> list[dict]:
"""Витягує функції з Python-модуля через AST"""
tree = ast.parse(source)
functions = []
for node in ast.walk(tree):
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
func_source = ast.get_source_segment(source, node)
complexity = self._calculate_cyclomatic_complexity(node)
functions.append({
"name": node.name,
"source": func_source,
"complexity": complexity,
"line_start": node.lineno
})
return sorted(functions, key=lambda x: x["complexity"], reverse=True)
def _calculate_cyclomatic_complexity(self, node) -> int:
"""Цикломатична складність — пріоритет для тестування"""
complexity = 1
for child in ast.walk(node):
if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler,
ast.With, ast.Assert)):
complexity += 1
elif isinstance(child, ast.BoolOp):
complexity += len(child.values) - 1
return complexity
| Параметр | Line coverage | Semantic coverage |
|----------|---------------|--------------------|
| Що вимірює | Виконані рядки | Покриті бізнес-сценарії |
| Приклад пропуску | — | None в агрегації, порожній список |
| Виявлення багів | Тільки у виконаних шляхах | Усі можливі входи |
| Середній час аналізу | Миттєво | Залежить від LLM (2-5 сек на функцію) |
<cite>«Після впровадження AI-системи клієнт відзначив: ми виявили 15 критичних багів, яких не знайшли ручні тести» — з відгуку клієнта</cite>
<details>
<summary>Приклад звіту про семантичні прогалини</summary>
```json
{
"gaps": [
{"scenario": "Empty list in aggregation", "importance": "high", "potential_bug": "ZeroDivisionError"}
]
}
Тест-генератор з мутаційним тестуванням
class AITestGenerator:
UNIT_TEST_PROMPT = """Згенеруй pytest unit-тести для функції.
Функція:
{function_code}
Непокриті сценарії (сфокусуйся на них):
{gaps}
Вимоги:
- Використовуй pytest + pytest-mock
- Параметризуй через @pytest.mark.parametrize де застосовно
- Для кожного тесту: Arrange-Act-Assert
- Тести на граничні значення
- Тести на помилкові вхідні дані
- Мок для зовнішніх залежностей
Поверни тільки код, без пояснень."""
async def generate_unit_tests(
self,
function_source: str,
gaps: list[dict]
) -> str:
gaps_text = "\n".join([
f"- {g['scenario']}: {g['importance']}"
for g in gaps[:5] # топ-5 за важливістю
])
result = await self.llm.ainvoke(
self.UNIT_TEST_PROMPT.format(
function_code=function_source,
gaps_text=gaps_text
)
)
return result.content
async def run_mutation_testing(self, source_file: str, test_file: str) -> dict:
"""Запускає мутаційне тестування через mutmut"""
import subprocess
result = subprocess.run(
["mutmut", "run", f"--paths-to-mutate={source_file}",
f"--tests-dir={test_file}"],
capture_output=True, text=True
)
# Аналізуємо вижилих мутантів (тести не спіймали зміну)
survived = self._parse_survived_mutants(result.stdout)
if survived:
additional_tests = await self._generate_for_mutants(survived, source_file)
return {"survived_count": len(survived), "additional_tests": additional_tests}
return {"survived_count": 0, "mutation_score": "100%"}
Мутаційне тестування — єдиний спосіб перевірити, чи дійсно тести ловлять помилки в логіці. Наш AI не тільки генерує тести, але й циклічно покращує їх, доки всі мутанти не будуть знищені. Це гарантує, що тести захищають саме від реальних дефектів, а не від формального покриття рядків.
Як AI-тестування вбудовується в CI/CD?
# .github/workflows/ai-qa.yml
name: AI QA Analysis
on:
pull_request:
types: [opened, synchronize]
jobs:
ai-test-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # потрібен для diff
- name: Analyze changed files
run: |
git diff origin/main...HEAD --name-only --diff-filter=AM | \
grep "\.py$" > changed_files.txt
- name: Run AI coverage analysis
run: |
python qa_system/analyze_coverage.py \
--changed-files changed_files.txt \
--generate-missing-tests \
--output coverage_report.json
- name: Comment PR with AI findings
uses: actions/github-script@v7
with:
script: |
const report = require('./coverage_report.json')
const comment = formatReport(report)
github.rest.issues.createComment({
issue_number: context.issue.number,
body: comment
})
Після інтеграції кожен PR отримує автоматичний коментар із переліком нових тестів, рівнем мутаційного покриття та списком невиправлених прогалин. Розробник може прийняти зміни або запросити додаткові тести — без ручного код-рев'ю тестів.
Що входить в роботу
- Аналіз поточного покриття. Запуск семантичного аналізатора на всій кодовій базі, вивантаження звіту з пріоритетами.
- Генерація тестів. Автоматичне створення unit-, інтеграційних та E2E-тестів для кожного виявленого пропуску.
- Мутаційне тестування. Цикл "генерація — запуск — покращення" до досягнення 100% мутаційного покриття.
- Налаштування CI/CD. Інтеграція аналізу в пайплайн (GitHub Actions, GitLab CI, Jenkins) з коментуванням PR.
- Документація. Документування всіх згенерованих тестів та методики їх підтримки.
- Навчання команди. Воркшоп з роботи з AI-системою та написання кастомних правил для вашого бізнесу.
- Підтримка 3 місяці. Безлімітні консультації та доопрацювання під нові версії коду.
Терміни
| Етап | Тривалість |
|---|---|
| Аналіз покриття + генерація unit-тестів | 3–4 тижні |
| Повна QA-система з CI/CD інтеграцією | 8–10 тижнів |
| Мутаційне тестування та E2E | +2–3 тижні |
Терміни можуть варіюватися залежно від розміру кодової бази та складності вимог. Ми пропонуємо безкоштовну попередню оцінку вашого проєкту за 1 день. Замовте її, і ми надамо детальний план впровадження.
Чому AI-тестування ефективніше за ручне?
| Критерій | Ручне тестування | AI-тестування |
|---|---|---|
| Покриття граничних випадків | Обмежене фантазією тестувальника | Систематичний перебір усіх комбінацій |
| Швидкість генерації | 1 тест за 15–30 хв | 100+ тестів за хвилину |
| Адаптація до змін | Ручне оновлення | Автоматичне самовідновлення |
| Виявлення багів | Частка від усіх можливих | До 95% семантичних дефектів |
Понад 5 років досвіду в AI/ML та 50+ впроваджених QA-систем. Ми гарантуємо, що після впровадження ви побачите реальне зниження багів у production, а не просто зростання метрик покриття. Отримайте консультацію: ми покажемо, як AI трансформує ваш QA-процес.







