Как заставить ИИ писать полезные тесты: простое руководство

Как заставить ИИ писать полезные тесты: простое руководство

Попросили ChatGPT написать тесты — получили десяток проверок. Всё зелёное, покрытие выросло. Радуетесь? Рано. Скорее всего, эти тесты бесполезны.

Запустите мутационное тестирование — измените в коде оператор сравнения, поменяйте константу, уберите проверку. Тесты остались зелёными? Вот и ответ. Проверки есть, но они ничего не ловят.

Проблема не в ИИ, а в том, как мы его используем. Разберёмся, что делать правильно.

Шаг 1: Сначала контракт, потом код

Не давайте ИИ код сразу. Сначала опишите, что функция должна делать.

Для API — используйте OpenAPI-схему. Перечислите эндпоинты, статус-коды, структуры данных, возможные ошибки.

Для функций — опишите типы параметров, что возвращает, какие исключения выбрасывает, какие граничные случаи должны обрабатываться.

Пример плохого промпта:

Напиши тесты для этой функции [вставил код]

Пример хорошего промпта:

Функция parseDate принимает строку и возвращает Date. Валидные форматы: "YYYY-MM-DD", "DD.MM.YYYY", "MM/DD/YYYY". При невалидном формате выбрасывает ParseError. При null/undefined выбрасывает ArgumentError. Должна корректно обрабатывать високосные годы. Напиши тесты с таблицей входов и ожидаемых результатов.

Видите разницу? Во втором случае ИИ знает, что именно проверять.

Шаг 2: Требуйте table-driven структуру

Не просите «напиши 10 тестов». Просите таблицу.

Создай таблицу с колонками: - Входные данные - Ожидаемый результат - Описание случая - Ожидаемая ошибка (если есть) Включи: - 3-4 позитивных сценария - Все граничные случаи (пустая строка, null, максимальная длина) - Негативные сценарии (невалидные форматы, некорректные типы)

Почему таблица? Потому что она заставляет думать систематически. Сразу видно, что забыли проверить пустой ввод или максимальное значение.

Добавлять новый кейс — значит добавить строку. Код компактный, читаемый, легко расширяется.

Шаг 3: Итерируйте — не пытайтесь всё за раз

Генерация за один запрос не работает. Нужны циклы.

Первый запрос: позитивные сценарии для штатных случаев. Запускаете, проверяете, что тесты проходят.

Второй запрос: негативные сценарии.

Добавь тесты для:

- Невалидных входов (некорректный формат, неверный тип)

- Граничных значений (null, пустая строка, максимальная длина)

- Отсутствующих обязательных полей

- Проверки сообщений об ошибках

Третий запрос: смотрите отчёт покрытия, находите непокрытые ветви.

В функции есть проверка if (value < 0). Сгенерируй тест, который пройдёт через эту ветвь.

Каждый раз — запуск, проверка, уточнение. Не накапливайте большие пачки непроверенного кода.

Подробнее про решение сложных задач с ИИ я писал в этом посте

Table-driven структура: систематичность против хаоса

Когда всё же нужны конкретные примеры, table-driven подход превращает набор тестов из свалки в систему. Вместо десятка отдельных функций — одна параметризованная с таблицей входов и ожидаемых результатов.

Просите ИИ сразу генерировать такую структуру. Колонки: входные параметры, ожидаемый выход, описание кейса, ожидаемая ошибка (если есть). Строки — конкретные сценарии. Такой формат заставляет думать систематически: сразу видно, что не хватает граничного значения или негативного сценария.

Преимущество очевидно — добавить новый кейс означает добавить строку в таблицу, а не копировать функцию целиком. Код компактный, читаемый, легко рефакторится. Но главное — таблица помогает выявить классы эквивалентности входов и осознанно выбрать представителей каждого класса.

Чек-лист перед принятием теста

Каждый сгенерированный тест должен пройти три проверки:

1. Запуск Тест стабильно проходит локально и в CI. Нет зависимостей от времени выполнения, порядка тестов, случайных данных.

2. Читаемость За 30 секунд понятно, что проверяет тест. Структура AAA (Arrange-Act-Assert) очевидна. Имена говорящие.

3. Ценность Тест ловит реальные баги. Проверьте мутационным тестированием — если mutation score низкий, ассерты слишком слабые.

Храните промпты как инфраструктуру

Когда находите промпт, который хорошо работает — сохраняйте его в репозиторий. Создайте папку docs/prompts/ или .ai-templates/. Складывайте туда шаблоны запросов: для генерации table-driven тестов, для property-based свойств, для метаморфных отношений, для проверок исключений.

По мере накопления опыта обновляйте шаблоны. Добавляйте примеры хороших и плохих результатов. Указывайте типичные ошибки и как их избегать. Это превращает хаотичный процесс в воспроизводимую практику.

Логируйте траекторию улучшений при итеративной генерации. Сохраняйте артефакты: отчёты покрытия, результаты мутационного тестирования, метрики качества. Прозрачность процесса критична для доверия команды.

Главное

ИИ не пишет тесты за вас. Он генерирует черновики. Ваша задача — проверить, что эти черновики действительно ловят баги.

Начинайте с описания контракта, а не кода. Требуйте table-driven структуру. Итерируйте короткими циклами. Проверяйте силу тестов мутационным анализом. Сохраняйте работающие промпты.

Автогенерированные тесты без критического анализа — это иллюзия защиты, хуже чем её отсутствие. Но правильно используя ИИ, можно значительно повысить качество покрытия при меньших затратах времени.

Подробнее об ИИ инструментах, которые позволили попасть в топ 5% лучших сотрудников Яндекса, рассказываю тут:

Нейросети с каждым годом обретают всё большую популярность и становятся умнее.

В эпоху столь быстрых изменений важно не отставать и осваивать новые инструменты. Их игнорирование приведёт к тому, что ты проиграешь конкуренцию тем, кто умеет использовать ИИ эффективно.

Получить план под СВОИ задачи, а не "ИИ для всех":

Месяц персонального менторинга по…

1
Начать дискуссию