Вот уже пару лет чат-боты, основанные на больших языковых моделях, «гремят» на весь интернет. Поражают своими возможностями и делают то, о чем около 15 лет назад можно было услышать только в фантастических сюжетах. При этом важно что, сейчас Large Language Model (LLM) дошли до широкого круга потребителей и все могут их увидеть и протестировать. В связи с этим возникают дискуссии, размышления, статьи-прогнозы на тему того, как искусственный интеллект (ИИ) изменит рынок труда, кого заменят, сократят, а кто останется и т.д. Профессия QA и процессы тестирования тоже не остались без подобных рассуждений.
Привет, Хабр! Меня зовут Андрей, я QA-специалист в компании SimbirSoft. В этой статье хочу поделиться опытом и впечатлениями моих коллег в использовании ИИ для рабочих задач.
Содержание статьи:
Применение ИИ в анализе ТЗ и создании тестов
Анализ ошибок и локализация багов
Создание отчетности о тестировании
ИИ в автоматизации тестирования (написании автотестов)
Если сильно упростить работу QA, то получится следующее:
Анализ требований (ТЗ) и создание тестов
Выполнение тестирования
Локализация багов
Отчетность о тестировании
Работы по автоматизации тестирования
Мы не будем рассматривать пункт «Выполнение тестирования» в его прямой формулировке, поскольку выполнить тесты можно автоматизированным или ручным способом. Написанию автотестов посвятим отдельный блок, а по ИИ-инструментам, которые заменяют ручное тестирование консистентных результатов, пока опыта не набралось :)
Таким образом, можно выделить следующие сферы, в которых рассмотрим применение ИИ:
Анализ ТЗ и написание тестовой документации
Анализ ошибок и локализация багов
Создание отчетности о тестировании
ИИ в автоматизации тестирования (написании автотестов)
Перед началом основной части статьи хочется обозначить некоторые моменты:
В данном материале понятия «ИИ», «Нейросеть», «LLM», «Языковая модель», «GPT», «бот» и т.д. предлагаю считать синонимами. Да, это не совсем корректно, но это и не научная статья, а скорее обзорная :)
Механики обучения, работы, формирования ответа ИИ рассматривать подробно и отдельно не будем, так как на эту тему уже есть много отличных материалов.
Практический опыт будет представлен в виде работы с «собирательным образом» ИИ, но с учетом того, какой именно GPT-бот применялся.
Применение ИИ в анализе ТЗ и создании тестов
Начнем с классики – того, что считается одной из трудоемких работ QA-специалиста — написание тестовой документации (ТД). Что нужно, чтобы создать тесты? Прочитать требования (ТЗ). Писать тестовую документацию долго и трудно, особенно, если это тест-кейсы, а не чек-листы. Чем сложнее и объемнее функционал, тем объемнее нужна документация. Поэтому от ее создания часто отказываются или сильно сокращают этот этап. И часто впоследствии возникают проблемы, связанные с падением качества ПО — общеизвестный факт в профессиональной среде QA.
Но писать ТД надо. Правильная тестовая документация приносит больше пользы, чем издержек. В конце концов, тестирование ПО — та же программа и методика испытаний (ПМИ), только в IT, а любая ПМИ предполагает список проверок, а также порядок их проведения.
Итак, мы определили, что писать тестовую документацию все же придется. Здесь напрашивается очевидное решение — отправить в нейросеть ТЗ и попросить написать тест-кейсы (или чек-листы).
Вот как описывает свой опыт Ирина, QA-специалист SimbirSoft:
Было необходимо очень быстро написать чек-листы и тест-кейсы на всю функциональность, поскольку предыдущий тестировщик этим не занимался. Чтобы ускорить процесс, я отправляла ТЗ частями и писала свой запрос ИИ. В итоге тестовая документация получалась очень скудной и «джуновской», никакую конкретику чат не дал. Все равно пришлось все руками писать.
Не так давно узнала, что есть отдельная профессия – промт-инженер, которые, по сути, такие же тестировщики, которые тестируют ИИ и обучают их верно распознавать входящий текст, обрабатывать и выдавать результат.
Если очень кратко, то в моем случае нужно было написать следующее: «Ты тестировщик бэкенда с опытом работы 5 лет, тебе необходимо сделать то и то. Если будут уточняющие вопросы, задавай». Так чат должен был понять, какого уровня ему выдавать ответы.
Кроме того, я использовала чат для написания мок-заглушек на Groovy. Ни одна заглушка без ошибок не прошла. Более того, она была составлена некорректно.
Я пробовала задать чату вопросы, на которые заранее знала ответ, понимая, что он не всегда отвечает со 100% точностью. Поэтому, на мой взгляд, он еще не настолько хорош в доступных версиях, чтобы его использовать в работе по вопросам, в которых сам кое-как разбираешься.
Сразу следует уточнить важное: отправлять в GPT-боты ТЗ, код и другие реальные артефакты строго не рекомендуется, поскольку, во-первых, таким образом, вы 100% нарушаете NDA, во-вторых, снижаете безопасность проекта (закрытая информация утекает во внешние системы).
Исходя из выводов Ирины выше — ответ бота по документации оказался неудовлетворительным, требующим серьезных доработок. Однако, я считаю, что главным препятствием для дальнейшего использования такого ответа является вопрос безопасности.
Но есть другой вариант — попросить нейросеть написать проверки для некой абстрактной страницы, формы, сущности.
Вот что получалось с разной периодичностью обращения к Chat GPT:
Запрос пользователя:
Напиши 3 тест-кейса для проверки формы регистрации
Ответ чата GPT:
Тест кейсы для формы регистрации:
1. Проверка обязательных полей:
* Описание: Проверить, что форма не позволяет отправить данные без заполнения обязательных полей (например, имя, пароль, email).
* Шаги:
1. Открыть форму регистрации.
2. Оставить одно или несколько обязательных полей пустыми.
3. Попытаться отправить форму.
4. Проверить, выводится ли сообщение об ошибке, указывающее на незаполненные обязательные поля.
* Ожидаемый результат: Форма не должна быть отправлена, и должно быть выведено сообщение об ошибке, указывающее на незаполненные обязательные поля.
2. Проверка валидации email:
* Описание: Проверить, что форма валидирует email адрес пользователя, чтобы он был в правильном формате.
* Шаги:
1. Открыть форму регистрации.
2. В поле email ввести некорректный адрес, например, без символа "@" или с неправильным доменом.
3. Попытаться отправить форму.
4. Проверить, выводится ли сообщение об ошибке, указывающее на некорректный формат email.
* Ожидаемый результат: Форма не должна быть отправлена, и должно быть выведено сообщение об ошибке, указывающее на некорректный формат email.
3. Проверка пароля на соответствие требованиям:
* Описание: Проверить, что форма валидирует пароль пользователя, чтобы он соответствовал установленным требованиям (например, минимальная длина, наличие цифр и специальных символов).
* Шаги:
1. Открыть форму регистрации.
2. В поле пароль ввести пароль, не соответствующий требованиям (например, слишком короткий, без цифр).
3. Попытаться отправить форму.
4. Проверить, выводится ли сообщение об ошибке, указывающее на несоответствие пароля требованиям.
* Ожидаемый результат: Форма не должна быть отправлена, и должно быть выведено сообщение об ошибке, указывающее на несоответствие пароля требованиям.
Все адекватно — классические проверки начала тестирования.
Что если попросить написать более сложные кейсы?
Запрос пользователя:
Напиши 3 более сложных тест-кейса для проверки формы регистрации
Ответ чата GPT:
Более сложные тест кейсы для проверки формы регистрации:
1. Проверка обработки ошибок при невалидных данных:
* Описание: Проверить, как форма реагирует на ввод невалидных данных, например, очень длинных строк, символов, не относящихся к языку ввода, и др.
* Шаги:
1. Открыть форму регистрации.
2. Ввести невалидные данные в различные поля формы, например:
* В поле "Имя" - ввести очень длинную строку, символы не из латиницы или кириллицы, специальные символы.
* В поле "Email" - ввести адрес с некорректным форматом или несуществующим доменом.
* В поле "Пароль" - ввести очень короткий пароль, пароль без цифр, пароль без специальных символов, пароль с одинаковыми символами.
3. Попытаться отправить форму.
4. Проверить, выводится ли сообщение об ошибке, корректно ли оно сформулировано и указывают ли ошибки на конкретную проблему в введенных данных.
5. Проверить, что форма не отправляется с невалидными данными и остается в том же состоянии, что и до отправки (например, не перенаправляется на другую страницу).
* Ожидаемый результат:
* Форма не должна быть отправлена с невалидными данными.
* Должно быть выведено сообщение об ошибке, которое ясно и понятно указывают на проблему с введенными данными (например, "Пожалуйста, введите корректный email адрес", "Пароль должен быть не менее 8 символов", "Имя может содержать только буквы и цифры").
* Форма должна оставаться в том же состоянии, что и до отправки (например, не перенаправляется на другую страницу).
2. Проверка работы формы при ограниченном подключении к Интернету:
* Описание: Проверить, как форма работает, когда интернет-соединение ограничено или отсутствует.
* Шаги:
1. Открыть форму регистрации.
2. Искусственно ограничить или отключить интернет-соединение.
3. Заполнить форму валидными данными.
4. Попытаться отправить форму.
5. Проверить, выводится ли сообщение об ошибке, связанное с отсутствием интернет-соединения.
6. Восстановить интернет-соединение.
7. Повторить попытку отправки формы.
8. Проверить, отправляются ли данные на сервер после восстановления интернет-соединения.
* Ожидаемый результат:
* При отсутствии интернет-соединения форма не должна быть отправлена.
* Должно быть выведено сообщение об ошибке, связанное с отсутствием интернет-соединения.
* После восстановления интернет-соединения форма должна быть отправлена на сервер.
3. Проверка безопасности форм при атаках XSS:
* Описание: Проверить, что форма защищена от атак XSS (Cross-Site Scripting), которые могут быть использованы для инъекции вредоносного кода на сайт.
* Шаги:
1. Изучить документацию по безопасности приложений, чтобы понять, как XSS атаки работают и как защититься от них.
2. Использовать инструменты для тестирования на уязвимости XSS (например, Burp Suite, OWASP Zap).
3. Попытаться ввести вредоносный код в форму регистрации через различные поля.
4. Проверить, как форма реагирует на ввод вредоносного кода (например, блокирует его, предотвращает его исполнение).
* Ожидаемый результат:
* Форма должна быть защищена от атак XSS.
* Вредоносный код не должен быть исполнен и не должен влиять на работу сайта.
Важно: Для тестирования на уязвимость XSS необходимо иметь достаточно знаний в области безопасности приложений и использовать специализированные инструменты.
Хорошие ответы :)
А если еще усложнить задачу?
Запрос пользователя :
Напиши 1 сложный тест-кейс для проверки формы регистрации
Ответ чата GPT:
Тест кейс: Проверка устойчивости формы регистрации к атаке SQL-инъекции
Описание: Проверить, что форма регистрации защищена от атак SQL-инъекции, которые могут быть использованы для несанкционированного доступа к базе данных.
Шаги:
1. Изучение:
* Просмотреть документацию по безопасности приложений, чтобы понять, как атаки SQL-инъекции работают и как защититься от них.
* Изучить основные методы предотвращения SQL-инъекций, такие как валидация ввода, использование prepared statements, и escape-символов.
2. Подготовка:
* Выбрать инструмент для тестирования на уязвимость SQL-инъекции (например, Burp Suite, OWASP Zap, SQLMap).
* Изучить структуру базы данных и поля, используемые в форме регистрации.
3. Проведение теста:
* Ввести специальные символы и SQL-команды в разные поля формы регистрации (например, имя, email, пароль) с целью изменить запрос к базе данных.
* Использовать инструменты для анализа ответа сервера и проверки на присутствие в нем данных из базы данных (например, имена других пользователей, пароли, конфиденциальная информация).
* Проверить логи сервера на присутствие подозрительных запросов к базе данных.
4. Анализ результатов:
* Оценить уязвимость формы регистрации к атаке SQL-инъекции.
* Определить причины уязвимости (например, отсутствие валидации ввода, использование неподготовленных запросов).
* Предложить решения для устранения уязвимости (например, внедрить валидацию ввода, перейти к использованию prepared statements).
Ожидаемый результат:
* Форма регистрации должна быть защищена от атак SQL-инъекции.
* Сервер не должен отвечать на вредоносные запросы к базе данных.
* В логи сервера не должны попадать подозрительные запросы к базе данных.
Дополнительные заметки:
* Тестирование на уязвимость SQL-инъекции должно проводиться опытной командой разработчиков, имеющей знание о безопасности приложений и баз данных.
* Не рекомендуется проводить такие тесты на живом сервере, так как это может привести к непредвиденным последствиям.
* Тестирование на уязвимость SQL-инъекции должно быть интегрировано в процесс разработки и регулярно проводиться для обеспечения безопасности приложения.
Важно: Тестирование на SQL-инъекцию требует значительных знаний в области безопасности приложений и должно проводиться опытной командой разработчиков.
Предложения Chat GPT по тест-кейсам получились хорошие и адекватные. И в целом нейросети с данной задачей справляются неплохо, но следует отметить несколько моментов:
Во всех примерах даны только негативные проверки, хотя в первую очередь должны проверяться позитивные сценарии. Для улучшения тестового покрытия в промте стоит указать создавать позитивные и негативные проверки.
Сгенерированные «сложные кейсы» не направлены на проверку редких кейсов и неочевидных логик, а просто требуют больших хардскилов для выполнения. Тут без специфики конкретного ТЗ не обойтись. Кейсы со сложной логикой придется делать самостоятельно.
Возможный разрыв между предложением нейросети и уровнем тестировщика. Проблема в следующем: если тестировщик сам не в состоянии накидать проверки, сможет ли он их провести?
Однако в процессе создания тестовой документации есть одна задача, с которой ИИ справляется на отлично — это генерация тестовых данных. Дайте чат-боту шаблон в любом формате и попросите сгенерировать по нему сущностей — в ответ получите десятки готовых вариантов.
Запрос пользователя:
Сгенерируй 5 JSON-объектов, содержащих информацию о пользователях, используя шаблон.
Шаблон - {
"id": 0,
"username": "string",
"firstName": "string",
"lastName": "string",
"email": "string",
"phone": "string",
"userStatus": 0
}
Ответ:
Вот пример реализации для создания пяти JSON-объектов пользователей, используя предоставленный вами шаблон:
[
{
"id": 1,
"username": "JohnDoe",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+1 425-678-9012",
"userStatus": 1
},
{
"id": 2,
"username": "JaneSmith",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.org",
"phone": "+1 206-789-1011",
"userStatus": 1
},
{
"id": 3,
"username": "SamWashington",
"firstName": "Sam",
"lastName": "Washington",
"email": "sam.washington@example.net",
"phone": "+1 987-654-3210",
"userStatus": 1
},
{
"id": 4,
"username": "AliceGreen",
"firstName": "Alice",
"lastName": "Green",
"email": "alice.green@example.com",
"phone": "+1 123-456-7890",
"userStatus": 1
},
{
"id": 5,
"username": "BobWhite",
"firstName": "Bob",
"lastName": "White",
"email": "bob.white@example.org",
"phone": "+1 098-765-4321",
"userStatus": 1
}
]
Можно также попросить бота превратить все это в Insert-скрипт:
Запрос пользователя:
Теперь напиши INSERT SQL-скрипт, который вставит сгенерированные тобой объекты в таблицу с именем TABLE_1.
Ответ:
Для вставки сгенерированных JSON объектов в таблицу с именем TABLE_1 вам потребуется подготовить SQL скрипт. Предполагаем, что у вас есть столбцы, соответствующие каждому полю в JSON объекте. Ниже приведен пример SQL скрипта, который вставляет пять объектов в таблицу TABLE_1:
INSERT INTO TABLE_1(id, username, firstName, lastName, email, phone, userStatus) VALUES (1, 'JohnDoe', 'John', 'Doe', 'john.doe@example.com', '+1 425-678-9012', 1), (2, 'JaneSmith', 'Jane', 'Smith', 'jane.smith@example.org', '+1 206-789-1011', 1), (3, 'SamWashington', 'Sam', 'Washington', 'sam.washington@example.net', '+1 987-654-3210', 1), (4, 'AliceGreen', 'Alice', 'Green', 'alice.green@example.com', '+1 123-456-7890', 1), (5, 'BobWhite', 'Bob', 'White', 'bob.white@example.org', '+1 098-765-4321', 1);
Этот скрипт вставляет каждый объект в строку таблицы. Обратите внимание, что вам нужно будет адаптировать этот скрипт под вашу конкретную базу данных и структуру таблицы.

Кроме этого, можно генерировать тесты-заглушки (рыба-тексты), изображения с различными сюжетами и в любом стиле и т.д. Так благодаря нейросетям данные для тестов и демо стали максимально приближенными к реальным.
Анализ ошибок и локализация багов
С созданием ТД с помощью ИИ мы разобрались. Проведение тестирования мы пропустили по причинам, которые объяснялись в вводной части. Переходим к следующему этапу работы QA – локализации дефектов. Это нетривиальный процесс и часто не быстрый, а так хочется отправить в нейросеть “error message” и попросить найти причину. Для начала проверим, может ли ИИ локализовывать логически.
Для этого дадим одну из стандартных задач собеседований:
Запрос пользователя:
В веб интерфейсе программы есть страница с формой создания пользователя и страница со списком пользователей. в форме создания пользователя есть три поля «Имя», «Фамилия», «Отчество». При создании мы ввели в каждое поле валидные данные и отправили форму. На странице со списком пользователей у созданного пользователя отчество отображается не целиком, а только первые 5 символов. Это баг – должно быть целое отчество.
Предложи варианты локализации этого бага учитывая клиент-серверную сущность приложения.
Ответ:
Баги, подобные этому, могут возникать как на стороне клиента (веб-интерфейс), так и на стороне сервера (логика приложения). Вот несколько возможных вариантов локализации проблемы:
Варианты локализации бага:
Вариант 1: Ограничение длины строки на стороне сервера
Ошибка может заключаться в том, что на стороне сервера ограничена длина строки для поля Отчество. Например, на сервере могут быть установлены ограничения на максимальную длину строк при записи данных в базу данных или при передаче данных между клиентом и сервером.
Вариант 2: Проблема с фронтендом
Возможно, проблема связана с тем, как фронтенд отображает данные. Если используется шаблонный язык типа React или Vue, то возможно, что в компоненте, отвечающем за вывод списка пользователей, имеется ошибка в шаблоне. Проверьте код, отвечающий за вывод списка пользователей, и убедитесь, что он корректно обрабатывает все возможные значения и правильно показывает их на экране.
Вариант 3: Ошибка на уровне базы данных
Серверная часть приложения может записывать в базу данных только первые пять символов отчества вместо всего отчества. Это может происходить из-за неверной конфигурации базы данных или проблем с индексами. Проверьте, нет ли ограничений на длину столбца в базе данных и как он отображается в модели данных на сервере.
Вариант 4: Проблемы с передачей данных между клиентом и сервером
При обмене данными между клиентом и сервером может возникнуть ошибка, которая приводит к тому, что сервер получает неполные данные. Убедитесь, что все данные корректно отправляются и принимаются на сервере.
Пошаговый план действий:
Анализ формы:
Убедитесь, что форма создания пользователя правильно принимает и передает данные. Используйте инструменты разработчика браузера для проверки сетевого трафика и структуры HTTP-запросов.
Работа с базой данных:
Проверьте структуру таблицы в базе данных, где хранятся пользователи. Убедитесь, что столбец Отчество допускает достаточно большую длину строки.
Контроль серверной логики:
Проанализируйте обработку данных на сервере. Убедитесь, что весь объем переданных данных сохраняется без сокращений.
Тестирование фронтенда:
Запустите автоматические тесты для страницы со списком пользователей. Они помогут выявить возможные ошибки в рендеринге данных.
Обновление кода:
Обновите соответствующую часть кода фронтенда и серверной части, чтобы устранить проблему с отображением отчества.
Подведение итогов
Для полной локализации проблемы необходимо провести комплексный анализ всех компонентов системы – от фронтенда до бэкенда и базы данных. Проверьте каждый шаг процесса передачи и обработки данных, чтобы найти источник ошибки и исправить его.
Довольно неплохо — предложения хорошие. Здесь стоит отвлечься и сказать, что соискатели до уровня мидл- в среднем отвечают на этот вопрос хуже в половине случаев. Какой-то из пунктов могут пропустить либо из-за очевидности, либо потому что не знают. У нейросети есть важное преимущество — очевидное она не пропускает.
А как ИИ справляется с анализом error message, стек-трейсов и т.д.? Это может быть очень полезно, потому что часто стек-трейсы очень длинные, а корневая причина скрыта где-то внутри них. Вот пример анализа стек-трейса на 32 000 символов:


Хороший результат, однако данный пример довольно простой — указание ошибки уже в нем было. Кроме того, в диалоговое окно поместилось только 3200 знаков, при том что полный стек-трейс содержит 32 000.
Продолжаем анализировать логи, после чего выявим несколько следствий:
Чем меньше в стек-трейсе явных указаний на ошибку, тем более общий неконкретный и бесполезный ответ даст нейросеть.
Запоминание контекста диалога приводит к деградации ответов. Все знают, что ИИ помнит предыдущие сообщения в чате — это позволяет ему хранить контекст и улучшать ответы. Но он делает это всегда, даже когда не требуется. В результате, если в один и тот же диалог присылать все новые и новые логи с ошибками, то в какой-то момент бот начнет путаться в вопросах, своих ответах, сращивать их и выдавать все более невалидные ответы. Данный факт был проверен на нескольких чат-ботах, и рано или поздно деградация ответов случалась, причем это происходило неожиданно. Вот пример анализа одного и того же стек-трейса в «замусоренном» диалоге (1) и в «чистом» (2):

В первом ответе ошибка никак не связана с кэшем, в логе об этом вообще не было сказано, однако рассуждения о кэше и о запросах select были подтянуты из других, не относящихся к данной ошибке логов.
Во втором ответе из «чистого» диалога нет конкретики, но в целом суть происходящего передана верно.
Совет: если анализируете много ошибок, почаще обновляйте диалог, особенно, если ошибки разнородные.
Создание отчетности о тестировании
Написать обзорный отчет по прогону тестирования — не такая простая задача, как кажется, а точнее, не всегда простая. Если мы говорим о регрессионном тестировании стабильного, долгоживущего продукта, то делать отчеты легко: можно взять предыдущий, ввести новые цифры, артефакты и выводы – готово. И это нормально, поскольку что-то принципиально новое происходит редко. Но если ваш продукт находится в стадии активных изменений или вы делаете отчет не о регрессе, тогда все сложнее. Набор тестов каждый раз разный, проблемы, выводы и заключения — тоже уникальные. Поэтому хочется сэкономить время и автоматизировать написание отчетов с помощью ИИ.
Для проверки возможности генерации отчета тестирования в «закромах» нашелся старый чек-лист о тестировании одного pet-проекта. В нем есть таблица с номерами, приоритетами, названиями и статусам прохождения проверок. Все это было превращено в CSV и отправлено в один из чат-ботов с запросом:

Бот подумал несколько секунд и дал ответ:


Примечание: «пройдено с багом» — авторский статус, указанный в источнике. Чем он отличается от «провалено» — неизвестно.

Что ж, обзорный отчет составлен неплохо. Раздела «Дополнительные проверки» в оригинальном файле нет, но, возможно, нейросеть сама вывела его. В целом основные моменты подсвечены и сделан краткий вывод. Попробуем улучшить отчет и добавить в него диаграммы. В этом же треде (чате) пишем запрос: «сделай диаграмму по статусам проверок». Получаем следующий ответ:

Здесь есть явные проблемы. И дело не в том, что диаграмма не очень «красивая», а в том, что статусы подсчитаны неверно. В представленном файле в статусе «пройдено» — 20 кейсов, а не 24; в статусе «пройдено с багом» — 7 проверок, а не 9. Всего в файле 28 кейсов, а не 35. Интересно, что 35 — это общее количество строк в файле.
Эксперименты в других чат-ботах по созданию отчета о тестировании на основе файла дали схожие результаты. Общий вывод такой: обзорный отчет «по верхам» нейросеть делает хорошо, но чем дальше углубляться и просить больше значимых деталей, тем больше ИИ спотыкается.
ИИ в автоматизации тестирования (написании автотестов)
Конечно, этот обзор был бы неполным без экспериментов по использованию автотестов с помощью ИИ. Создание набора рабочих автотестов — трудоемкий процесс, требующий времени и специалистов с определенными навыками. Но это выгодно, потому что автоматизируется, ускоряется и удешевляется регресс (в первую очередь), а также другие виды тестирования. Кроме того, о замене разработчиков ИИ-ботами в сети говорят очень много, так как тема довольно злободневная и актуальная. Но зачастую работу нейросетей с фреймворками тестирования в подобных дискуссиях и различных публикациях не обсуждается. А как же боты пишут код именно тестов?
Если Chat GPT попросить написать автотест на Java для проверки отправки POST-запроса с сериализацией данных класса в тело запроса, то ответ будет примерно таким:

Код подробно задокументирован и выглядит неплохо. Стоит отметить, что использование Spring RestTemplate — довольно необычный ход. В тестах более распространен Rest Assured, но это не проблема. Однако такие примеры мне не нравятся, поскольку недостаточно показательны: они ничего конкретно не тестируют, а также не несут практической нагрузки. Подобный код-болванка легко находится с помощью поисковика, поэтому мы с вами разберем, как ИИ справляется с более прикладными задачами.
Представим, что нам нужно в коде получать значения переменных из файла .gitlab-ci.yml. Это очень удобно для тестов, так как с помощью такого приема вы сможете запускать тесты на разные стенды, выбирать обращения к эндпойнтам через различные варианты фасадов и прокси, а также многое другое.
Я сформулировал следующее задание и отправил его в один из чат-ботов:
Вопрос:
В файле .gitlab-ci.yml есть переменная PATH_TO_ENDPOINT, которая имеет value: "variant1". В коде программы есть класс Experiment.kt. В классе Experiment.kt есть переменная pathType значение, которой нужно взять из PATH_TO_ENDPOINT.
Напиши пример, как это сделать, используя язык программирования Kotlin.
Ответ:
Для того чтобы использовать значение переменной PATH_TO_ENDPOINT
в вашем коде на Kotlin, вам потребуется загрузить значения конфигурации из вашего файла .gitlab-ci.yml
. Предположим, что этот файл находится в корне проекта. Вот пример кода, который может вам помочь:
```kotlin
// Импортируем необходимые библиотеки для работы с конфигурацией
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import java.io.File
import javax.script.ScriptEngineManager
class EndpointLoader(private val logger: Logger) {
private val scriptEngine = ScriptEngineManager().getEngineByName("JavaScript")
fun loadEndpoint(): String? {
// Загружаем файл .gitlab-ci.yml
val gitLabCiYmlPath = File("./${System.getProperty("user.dir")}/.gitlab-ci.yml").absolutePath
try {
val result = scriptEngine.eval("var jsonContent = JSON.parse(require('fs').readFileSync(${gitLabCiYmlPath}, 'utf8')); return jsonContent['PATH_TO_ENDPOINT'];") as String
if (result == null || result.isEmpty()) {
throw IllegalArgumentException("Invalid value for PATH_TO_ENDPOINT in ${gitLabCiYmlPath}")
}
return result
} catch (e: Exception) {
logger.error("Error loading PATH_TO_ENDPOINT from $gitLabCiYmlPath", e)
return null
}
}
}
fun main() {
val logger = Logger.getInstance(Experiment::class.java)
val loader = EndpointLoader(logger)
val endpointValue = loader.loadEndpoint() ?: "DefaultEndPoint"
println("Loaded endpoint: $endpointValue")
// Теперь вы можете использовать endpointValue в вашем классе Experiment.kt
class Experiment {
var pathType: String = endpointValue
// Другие методы класса Experiment...
}
}
```
Пояснение:
1. Используем ScriptEngineManager
и JSON.parse
для чтения содержимого файла ``.gitlab-ci.yml.
2. Получаем значение переменной PATH_TO_ENDPOINT
и возвращаем его.
3. Обрабатываем возможные исключения при чтении файла.
4. Вызываем метод main()
, который создает экземпляр EndpointLoader
, загружает значение переменной PATH_TO_ENDPOINT
и использует его в классе Experiment
.
Таким образом, ваш код будет загружать значение переменной PATH_TO_ENDPOINT
из файла .gitlab-ci.yml
и использовать его в вашем коде на Kotlin.
Тут и загрузка файла, и парсинг, и обработка ошибок. И, возможно, этот пример и будет работать, только в реальности он мало применим. К тому же Kotlin стремится к лаконичности функций, а это явно не похоже на упрощенку. Я решил использовать другую нейросеть и задал ей тот же самый вопрос путем копипасты. Без малейшего изменения.
При этом получил другой ответ:
Чтобы использовать переменную окружения из файла .gitlab-ci.yml
в программе на Kotlin, вы можете воспользоваться стандартной библиотекой Kotlin для доступа к переменным окружения. Вот пример того, как это сделать.
1. Убедитесь, что переменная окружения PATH_TO_ENDPOINT
правильно настроена в вашем .gitlab-ci.yml
. Например:
yaml
variables:
PATH_TO_ENDPOINT: "variant1"
2. В вашем классе Experiment.kt
вы можете получить значение переменной PATH_TO_ENDPOINT
, используя функцию System.getenv()
. Вот пример, как это можно реализовать:
kotlin
class Experiment {
val pathType: String? = System.getenv("PATH_TO_ENDPOINT")
fun printPathType() {
if (pathType != null) {
println("The path type is: $pathType")
} else {
println("PATH_TO_ENDPOINT is not set.")
}
}
}
fun main() {
val experiment = Experiment()
experiment.printPathType()
}
### Объяснение кода:
- System.getenv("PATH_TO_ENDPOINT")
— это функция, которая возвращает значение переменной окружения с именем PATH_TO_ENDPOINT
. Если переменная не существует, она вернет null
.
- В классе Experiment
мы инициализируем переменную pathType
значением переменной окружения.
- Метод printPathType
выводит текущее значение pathType
.
Совсем другое дело. Строка val pathType: String? = System.getenv("PATH_TO_ENDPOINT") – то, что нужно. К слову, ту же самую информацию можно отыскать через классический поисковик по первой же ссылке. И еще: перед публикацией данной статьи я решил перепроверить это задание в первом чат-боте, и на этот раз он уже выдал «нормальный» совет — использовать System.getenv("PATH_TO_ENDPOINT"). При этом сама версия модели данного чат-бота не менялась, формулировка вопроса — тоже. Но во второй раз ИИ дал адекватный совет, непонятно почему.
Из всего этого можем сделать сразу несколько выводов:
Во-первых, качество советов по коду может значительно отличаться у нейросетей разных вендоров.
Во-вторых, даже одна и та же нейросеть может давать разную «адекватность» советов в разное время.
В-третьих, пользователь ИИ-бота должен уметь «на глаз» определять качество ответа, для этого ему необходимо должным образом разбираться в языке программирования.
Другой интересный пример. С помощью Awaitility (для асинхронного тестирования) и AssertJ (для выражения утверждений) была написана достаточно объемная тестовая функция, которая периодически делает запрос и проверяет ответ на наличие маркеров успеха или провала. Эта функция умеет выдавать Success или Exception в зависимости от проверки утверждений. Проблема в том, что для формирования отчетов использовался модуль Allure, который относит к failed-тестам только Assert Error, а любой Exception относит к broken-тестам, то есть, к кейсам, которые сломались и не дошли до конца. В данном случае требовалось завернуть тестовую функцию внутрь другой, которая будет сводить результат до Success или Assert Error. Для этого я написал такой промт:
У меня есть написанный на Kotlin тестовый метод customMessage, который выглядит так:
fun customMessage() { val integer = 1 assertThat(integer).isEqualTo(0) }
Мне нужно внедрить assertThat(integer).isEqualTo(0) внутрь другой конструкции assert, которая будет проверять, выполнен внутренний assertion или нет.
Ответ:

И объяснение:

Компактная функция, но меня сразу смутил assertFailsWith<AssertionError>. Я вчитывался в объяснение и попытался понять, почему так, после чего поменял в исходном промте assertThat(integer).isEqualTo(0) на assertThat(integer).isEqualTo(1).
Ответ сразу изменился:
fun customMessage() {
val integer = 1
assertThatCode { assertThat(integer).isEqualTo(1) }
.doesNotThrowAnyException()
}
В чем же дело? В блоке, кода я объявил integer = 1, но ожидал isEqualTo(0). Я сделал это специально, поскольку экспериментировал над трансформацией ошибок, а также с их текстами. Поэтому нужен был тест, который бы проваливался постоянно. Но я не учел (и не предполагал), что нейросеть посчитает такое поведение обязательным и подстроит под него весь дальнейший код.
То есть, понимание чат-бота, что в условии задачи важно, а что нет, может сильно отличаться от вашего. И чем больше контекста, тем больше вероятность расхождений. Поэтому для улучшения качества ответа, я бы дал следующие советы:
Указывайте в промте только необходимый объем информации. Старайтесь не предоставлять лишнего.
Если ответ нейросети кажется странным, внимательно посмотрите на промт — сделайте его более структурированным или поменяйте формулировку.
Однако есть и положительные примеры кода от нейросетей. Например, однажды у меня была задача парсить SQL-скрипты и извлекать из них имена таблиц. Делать это нужно было с помощью строковых функций PostgreSQL. Я мало работал со строковыми функциями, поэтому пошел читать документацию к PostgreSql. Прочитанное мне не очень понравилось, стиль изложения мне не подошел и я обратился к нейросети.
Запрос был таким:
Есть база данных на движке PostgreSQL. В Таблице Table_1 есть ячейка query_text, в которой содержится строка: “Равным образом дальнейшее развитие различных форм деятельности играет важную schema1_Customers роль в формировании системы schema1_Employees обучения кадров, соответствует насущным потребностям schema1_Categories.”
Напиши скрипт, который извлечет все подстроки schema1_
Содержание ячейки query_text я скомбинировал из текста-рыбы и случайных названий таблиц. Все это наиболее подходящим образом имитирует SQL-скрипты.
Нейросеть предоставила такой ответ:
SELECT unnest(regexp_matches(query_text, 'schema1_\w+', 'g')) AS match
regexp_matches – функция PostgreSQL, которая находит все совпадения регулярного выражения в строке.
unnest – функция PostgreSQL, которая служит для преобразования массива значений в набор строк. Она позволяет развернуть элементы массива в отдельные строки результата.
'schema1_\w+' – регулярное выражение, которое ищет строку, начинающуюся с schema1_, за которым следует одна или несколько букв, цифр или символов подчеркивания (\w+).
'g' – флаг, означающий глобальный поиск, то есть будут найдены все вхождения подстрок, а не только первое.
Полученный результат мне полностью подошел. Но особенно порадовало понятное мне объяснение. Я попросил пояснить и дать примеры функции regexp_matches с шаблонами и флагами, на что получил наиболее понятный (для меня) ответ, чем в документации.
По возможностям написания кода тестов с помощью нейросетей я сделал для себя следующие выводы. Чат-боты хорошо подходят для задач «последнего шага». То есть, когда вы точно знаете, какого поведения нужно добиться, какие входные данные (в метод/функцию/класс) должны быть, желаемый внешний вид кода, можете провалидировать результат, но не знаете, как конкретно сделать этот код. Нейросеть вам в этом поможет.
Кроме этого, чат-боты хорошо умеют объяснять какие-либо функции и фичи языков программирования. Большим плюсом здесь являются наглядные примеры, а также возможность уточнить любой момент или переформулировать ответ, если непонятно. Также, если нужен какой-то простой шаблон-скелет кода, то его также можно сгенерировать с помощью нейросети.
Заключение
Итак, на мой взгляд, общее впечатление от использования ИИ в тестировании неоднозначное. Хочу подытожить и выделить те задачи, с которыми нейросети справляются хорошо, с какими средне, а с какими не очень.
Что получается хорошо:
Генерация тестовых данных по шаблону. Отличная вещь! Самая правильная работа для нейросети – генерировать сущности, похожие на реальные.
Создание черновика для тестовой документации. Нейросеть не забывает банальные проверки и в целом базовый набор кейсов получается достойный.
Быть интерактивным учебником. ИИ обстоятельно и с примерами умеет объяснять код, функции ЯП. Чаще всего эти объяснения дельные и помогают решить проблему.
Что получается со средней эффективностью:
Написание кода тестов. Почему я отнес этот пункт к средним успехам? Качество генерации напрямую зависит от того, как ставятся задачи нейросети. Код хорошо работает только для простых и шаблонных тестов. Я часто пользуюсь ИИ для «последнего шага» при написании кода. Но вместе с этим качество кода резко снижается, если нужно написать что то нетривиальное, либо, например, создать свой микрофреймворк. Также существует проблема, что на один и тот же вопрос ответы разных чат-ботов могут быть разными, более того, у одного и того же бота сегодня могут быть ответы одни, а через неделю уже другие. В половине случаев нужно использовать другую LLM для перепроверки.
Что получается скорее плохо:
Локализация ошибок по стек-трейсам. Практически бесполезна. Работает хорошо, только если в стеке есть явное указание на ошибку. Локализация по описанию воспроизведения ошибки в действительности еще более бесполезна, потому что дольше придется описывать контекст, чем самостоятельно локализовывать. В целом, чем лучше знаешь систему, тем меньше пользы от ИИ в этом деле.
Создание отчетности о тестировании на основе входного файла. Все потому что LLM часто (почти в каждом случае) путает причину и следствие (особенно ИИ не любит названия тест-кейсов) и делает в отчете значимые ошибки в подсчетах и выводах. Вероятность этого получилось уменьшить путем подготовки входного файла, но время на такую подготовку затрачивается довольно много, а в итоге профит от использования LLM обнуляется.
Кроме всего этого, при использовании облачных нейросетей почти всегда приходится заменять названия, состав, контекст сущностей, чтобы не передавать чувствительную информацию. Это неприятно и неудобно, поскольку значительно расходуются время и фантазия.
Таким образом, ИИ может гораздо упростить вашу работу, показать отличный и качественный результат за минуты, за который еще вас и похвалят :) Но в то же время ИИ может выдать ошибочные данные, неверный вывод, код и т.д, что можно не сразу заметить, тогда за эти ошибки спросят именно с вас, а не с бота.
Удачи на проектах! :)
Спасибо за внимание!
Больше авторских материалов для QA-специалистов от моих коллег читайте в соцсетях SimbirSoft – ВКонтакте и Telegram.