После каждого изменения кода приходится проверять старые сценарии, новые условия и неожиданные входные данные. Искусственный интеллект помогает перенести часть этой рутины в автоматические проверки: составить unit-тесты, предложить неочевидные входные данные, разобраться с падением теста.
При этом использование ИИ в тестировании особенно полезно там, где поведение функции можно описать однозначно. В статье разберём практический процесс: от постановки задачи модели до ревью и запуска полученных проверок.
Что такое ИИ в тестировании кода
Это применение языковых моделей (LLM), AI-ассистентов и AI-IDE для анализа исходников, подготовки тестовых сценариев, генерации автотестов и разбора ошибок.
Обычный ИИ для программирования может написать функцию или объяснить её устройство. При тестировании задача другая: найти условия, в которых функция поведёт себя неправильно, и выразить ожидаемый результат через проверяемые утверждения — assertions.
Обычно нейросети в тестировании работают с текстовым представлением кода и требований. Они способны заметить пропущенную ветку if или предложить проверку на пустую коллекцию, но не знают требований к продукту, если вы их не сообщили.
В отличие от обычного запуска тестового фреймворка, AI в тестировании помогает придумать сами сценарии и подготовить код проверок. При этом модель не выполняет тесты просто потому, что написала их.
Где ИИ помогает при тестировании кода
Генерация unit-тестов
Unit-тест проверяет отдельную функцию, метод или небольшой модуль, по возможности изолированный от базы данных, сети и других внешних зависимостей. Поэтому его результат обычно проще воспроизвести и объяснить, чем результат сквозной проверки приложения.
Например, для функции расчёта скидки можно попросить позитивные сценарии (скидка применяется), негативные (неподходящий промокод отклоняется) и граничные (заказ на один рубль ниже порога). Такая генерация unit-тестов ускоряет создание первоначального набора проверок, но правильные значения в assert должны следовать из требований, а не только из текущей реализации.
Инструменты, работающие прямо с репозиторием, могут учитывать импорты, соглашения об именовании и существующие тесты. О различиях таких сред рассказываем в обзоре лучших AI-IDE.
Поиск edge cases и слабых мест в логике
Типовые проверки часто охватывают «счастливый путь»: корректные данные приводят к корректному результату. Ошибки же прячутся на границах. Попросите модель перечислить edge cases, не создавая тесты сразу. Так проще сначала оценить предложенные сценарии, а потом превратить нужные в код.
Особенно полезно проверить ноль, отрицательные числа, пустые строки и списки, None или null, неверные типы, дубли, большие значения, несовпадающие часовые пояса, а также сочетания нескольких условий.
Пример: функция разрешает бесплатную доставку от 3000 рублей включительно. Тесты на 2500 и 4000 рублей не обнаружат ошибку в условии > 3000. Проверка ровно на 3000 — обнаружит.
Анализ ошибок и падающих тестов
Когда тест не проходит, ИИ можно передать само утверждение, фрагмент реализации, сообщение об ошибке и stack trace. Модель сопоставит ожидаемый и фактический результат, предложит гипотезы: ошибка в условии, неправильный mock, неверно подготовленные тестовые данные или некорректное ожидание.
Хороший результат анализа — проверяемые гипотезы, а не категоричный диагноз. Исправление нужно запускать и проверять отдельно: объяснение LLM само по себе ничего не доказывает.
Подготовка mocks, fixtures и тестовых данных
Если функция обращается к внешнему API, в unit-тесте этот вызов часто подменяют mock-объектом. Он возвращает заранее заданные данные и позволяет проверить, с какими аргументами вызвали зависимость. Fixture создаёт повторяемое окружение: например, тестового пользователя, настройки или временный файл.
ИИ умеет заготовить mocks и fixtures под pytest, Jest или JUnit, предложить наборы входных и выходных данных. Если важен реальный контракт между сервисами, потребуются и интеграционные проверки: mock не покажет, что внешняя система действительно отвечает ожидаемым образом.
ИИ в автоматизации тестирования
Этот подход полезен не только при создании нового файла с тестами. Он помогает расширить регрессионный набор после исправления бага, привести однотипные проверки к параметризованному виду и подготовить тесты для запуска в CI/CD.
Иногда применяют и агенты ИИ в тестировании: агент может изучить несколько файлов, создать тесты, запустить команду, прочитать ошибку и предложить исправление.
Как генерировать unit-тесты с помощью ИИ
Чтобы получить пригодные проверки, недостаточно написать «покрой функцию тестами». Нужен небольшой контракт: что функция принимает, что должна возвращать и какие ошибки считать ожидаемыми. Здесь работает та же логика, что и в промпт-инжиниринге: конкретика полезнее длинного, но расплывчатого запроса.
- Выберите единицу проверки. Начните с функции с понятными входами и выходами. Для большого класса выделите метод и его зависимости.
- Укажите стек. Язык, версию, тестовый фреймворк (
pytest,Jest,JUnit), способ импорта и правила проекта. - Опишите ожидаемое поведение. Зафиксируйте бизнес-правила, допустимые значения, исключения, условия на границах и принцип округления, если он важен.
- Попросите сначала матрицу сценариев. Пусть ИИ перечислит вход, ожидаемый выход и причину проверки. Удалите лишнее и дополните пропущенные ветки.
- Получите тестовый код. Попросите параметризацию повторяющихся случаев и минимальные заглушки там, где без них не обойтись.
- Запустите тесты в окружении проекта. Разберите падения, исправьте неверные ожидания или обнаруженный дефект, затем повторите запуск.
Для больших кодовых баз важен не только промпт, но и контекст проекта: доступ к сигнатурам, зависимостям и соседним тестам помогает не выдумывать структуру репозитория. При этом возможность подключить контекст не гарантирует, что модель правильно его истолкует.
Генерация unit-тестов: практический пример на Python
Представим функцию расчёта доставки. По требованиям обычная доставка стоит 300 рублей при сумме заказа меньше 3000 рублей и бесплатна начиная с 3000. Экспресс-доставка всегда стоит 600 рублей. Отрицательная сумма запрещена.
В коде разработчик ошибся в одном символе:
# delivery.py
def shipping_fee(total: int, express: bool = False) -> int:
if total < 0:
raise ValueError("negative total")
if express:
return 600
return 0 if total > 3000 else 300 # Ошибка: нужно >=
Проверка, построенная по текущему коду, может повторить это неверное условие. А тест, построенный по требованиям, зафиксирует дефект:
# test_delivery.py
import pytest
from delivery import shipping_fee
@pytest.mark.parametrize("total,express,expected", [
(0, False, 300),
(2999, False, 300),
(3000, False, 0),
(3001, False, 0),
(3000, True, 600),
])
def test_shipping_fee(total, express, expected):
assert shipping_fee(total, express) == expected
def test_negative_total():
with pytest.raises(ValueError):
shipping_fee(-1)
Запуск python -m pytest -q покажет падение на значении 3000: функция вернёт 300 вместо ожидаемого 0. После замены > на >= все приведённые случаи должны пройти. Использованный декоратор @pytest.mark.parametrize поддерживается официальной документацией pytest.
Смысл примера не в количестве тестов, а в независимом источнике ожиданий. Если бы модель выводила правила только из исходного кода, она могла бы уверенно подтвердить уже существующий баг. Правила продукта должны оставаться главным ориентиром.
Примеры запросов к ИИ для тестирования кода
Запрос на написание unit-тестов
Слабый: «Напиши тесты для этого метода».
Сильный:
Проект на Python 3.12, тесты пишем на pytest. Ниже функция
shipping_feeи правила расчёта доставки. Сначала составь таблицу позитивных, негативных и граничных сценариев. Затем создайtest_delivery.py, используя параметризацию. Не меняй исходную функцию. Для каждого теста укажи, какое требование он проверяет. Если поведение не определено, задай вопрос, а не придумывай правило.
Если работа ведётся в Kodik, такой запрос можно дополнить просьбой изучить соседние тесты и принятые в проекте соглашения. Доступ к файлам помогает согласовать стиль тестов, но ожидаемую бизнес-логику всё равно нужно описать явно.
Запрос на поиск пограничных случаев
Слабый: «Найди баги в функции».
Сильный:
Проанализируй метод оформления заказа на TypeScript. Его контракт и код приведены ниже. Найди возможные edge cases: пустая корзина, повторный промокод, отрицательное количество, ошибка платёжного API, дублирующий запрос. Верни таблицу: условие, риск, ожидаемое поведение по требованиям, предлагаемый тест. Если в требованиях пробел, пометь его как вопрос. Пока не переписывай код.
Этот приём особенно полезен перед рефакторингом: разработчик заранее видит, какие ветки ещё не зафиксированы тестами. Но не стоит автоматически превращать все предположения модели в требования к продукту.
Запрос на анализ падающего теста
Слабый: «Исправь тест, он падает».
Сильный:
Вот реализация, тест, полный stack trace и версии библиотек. Ожидаемое поведение описано отдельно. Назови до трёх наиболее вероятных причин падения и предложи минимальный способ проверить каждую. Разделяй ошибку в продукте, ошибку в тесте и проблему окружения. Не меняй assertion только ради зелёного статуса; если предлагаешь патч, объясни, почему он соответствует контракту.
Такая постановка не даёт модели пойти по самому простому пути — подогнать тест под фактический результат.
Где ИИ может ошибаться при генерации тестов
- Подмена требований реализацией. Модель изучает функцию и воспринимает её текущее поведение как правильное. Тест закрепляет баг вместо того, чтобы его обнаружить.
- Вымышленные API. В тестах появляются несуществующие методы, неподдерживаемые аргументы или импорты из другой версии библиотеки. Такие проверки не запускаются.
- Ложное чувство покрытия. Процент строк в отчёте может быть высоким, хотя критические условия и исключения не проверены. Метрика покрытия показывает, что выполнялось, но не доказывает качество утверждений.
- Хрупкие mocks. Избыточные заглушки делают тест зависимым от внутреннего устройства функции. После безобидного рефакторинга он ломается, хотя поведение не изменилось.
- Неправильные тестовые данные. Модель предлагает значения, невозможные в доменной модели, либо пропускает ограничения, заданные схемой базы данных.
Поэтому ревью тестов включает три разных вопроса: запускается ли проверка, проверяет ли она нужное поведение и обнаружит ли она реалистичную ошибку. Для последнего можно временно изменить условие или результат функции и убедиться, что соответствующий тест падает.
Не стоит отдавать агенту безусловное право «чинить всё до зелёного статуса». ИИ-агенты в разработке могут выполнять цепочки действий, но при неверно заданной цели способны удалить важную проверку или изменить ожидание вместо исправления дефекта. Просматривайте diff и запускайте регрессионные тесты перед слиянием изменений.
Безопасность при работе с кодом и тестами
Для генерации тестов модели часто нужен фрагмент реализации, а иногда — доступ ко всему репозиторию. Прежде чем отправлять данные во внешний сервис, проверьте правила компании, настройки хранения запросов, права подключения и перечень файлов, которые инструмент сможет прочитать.
Не передавайте без необходимости пароли, токены, API-ключи, приватные конфигурации, персональные данные и содержимое закрытых репозиториев. Секреты могут попасть не только в промпт, но и в stack trace, лог ошибки или fixture. Для снижения риска используют маскирование чувствительных данных, в том числе KodikShield, и ограничивают доступ агента только нужными ресурсами.
Тестируйте код с ИИ в контексте проекта. Kodik помогает анализировать исходники, готовить unit-тесты, искать граничные случаи и разбирать ошибки прямо в процессе разработки. При этом результаты остаются предметом обычного ревью и запуска тестов. Скачать Kodik.



