ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт. qa.. qa. qa automation.. qa. qa automation. qa тестирование.. qa. qa automation. qa тестирование. Блог компании SimbirSoft.. qa. qa automation. qa тестирование. Блог компании SimbirSoft. искусственный интеллект.. qa. qa automation. qa тестирование. Блог компании SimbirSoft. искусственный интеллект. Тестирование IT-систем.. qa. qa automation. qa тестирование. Блог компании SimbirSoft. искусственный интеллект. Тестирование IT-систем. тестирование веб-приложений.

Вот уже пару лет чат-боты, основанные на больших языковых моделях, «гремят» на весь интернет. Поражают своими возможностями и делают то, о чем около 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);

Этот скрипт вставляет каждый объект в строку таблицы. Обратите внимание, что вам нужно будет адаптировать этот скрипт под вашу конкретную базу данных и структуру таблицы.

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 1

Кроме этого, можно генерировать тесты-заглушки (рыба-тексты), изображения с различными сюжетами и в любом стиле и т.д. Так благодаря нейросетям данные для тестов и демо стали максимально приближенными к реальным.

Анализ ошибок и локализация багов

С созданием ТД с помощью ИИ мы разобрались. Проведение тестирования мы пропустили по причинам, которые объяснялись в вводной части. Переходим к следующему этапу работы QA – локализации дефектов. Это нетривиальный процесс и часто не быстрый, а так хочется отправить в нейросеть “error message” и попросить найти причину. Для начала проверим, может ли ИИ локализовывать логически.

Для этого дадим одну из стандартных задач собеседований:

Запрос пользователя: 

В веб интерфейсе программы есть страница с формой создания пользователя и страница со списком пользователей. в форме создания пользователя есть три поля «Имя», «Фамилия», «Отчество». При создании мы ввели в каждое поле валидные данные и отправили форму. На странице со списком пользователей у созданного пользователя отчество отображается не целиком, а только первые 5 символов. Это баг – должно быть целое отчество.

Предложи варианты локализации этого бага учитывая клиент-серверную сущность приложения.

Ответ:

Баги, подобные этому, могут возникать как на стороне клиента (веб-интерфейс), так и на стороне сервера (логика приложения). Вот несколько возможных вариантов локализации проблемы:

Варианты локализации бага:

Вариант 1: Ограничение длины строки на стороне сервера

Ошибка может заключаться в том, что на стороне сервера ограничена длина строки для поля Отчество. Например, на сервере могут быть установлены ограничения на максимальную длину строк при записи данных в базу данных или при передаче данных между клиентом и сервером.

Вариант 2: Проблема с фронтендом

Возможно, проблема связана с тем, как фронтенд отображает данные. Если используется шаблонный язык типа React или Vue, то возможно, что в компоненте, отвечающем за вывод списка пользователей, имеется ошибка в шаблоне. Проверьте код, отвечающий за вывод списка пользователей, и убедитесь, что он корректно обрабатывает все возможные значения и правильно показывает их на экране.

Вариант 3: Ошибка на уровне базы данных

Серверная часть приложения может записывать в базу данных только первые пять символов отчества вместо всего отчества. Это может происходить из-за неверной конфигурации базы данных или проблем с индексами. Проверьте, нет ли ограничений на длину столбца в базе данных и как он отображается в модели данных на сервере.

Вариант 4: Проблемы с передачей данных между клиентом и сервером

При обмене данными между клиентом и сервером может возникнуть ошибка, которая приводит к тому, что сервер получает неполные данные. Убедитесь, что все данные корректно отправляются и принимаются на сервере.

Пошаговый план действий:

Анализ формы:

Убедитесь, что форма создания пользователя правильно принимает и передает данные. Используйте инструменты разработчика браузера для проверки сетевого трафика и структуры HTTP-запросов.

Работа с базой данных:

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

Контроль серверной логики:

Проанализируйте обработку данных на сервере. Убедитесь, что весь объем переданных данных сохраняется без сокращений.

Тестирование фронтенда:

Запустите автоматические тесты для страницы со списком пользователей. Они помогут выявить возможные ошибки в рендеринге данных.

Обновление кода:

Обновите соответствующую часть кода фронтенда и серверной части, чтобы устранить проблему с отображением отчества.

Подведение итогов

Для полной локализации проблемы необходимо провести комплексный анализ всех компонентов системы – от фронтенда до бэкенда и базы данных. Проверьте каждый шаг процесса передачи и обработки данных, чтобы найти источник ошибки и исправить его.

Довольно неплохо — предложения хорошие. Здесь стоит отвлечься и сказать, что соискатели до уровня мидл- в среднем отвечают на этот вопрос хуже в половине случаев. Какой-то из пунктов могут пропустить либо из-за очевидности, либо потому что не знают. У нейросети есть важное преимущество — очевидное она не пропускает.

А как ИИ справляется с анализом error message, стек-трейсов и т.д.? Это может быть очень полезно, потому что часто стек-трейсы очень длинные, а корневая причина скрыта где-то внутри них. Вот пример анализа стек-трейса на 32 000 символов:

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 2
ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 3

Хороший результат, однако данный пример довольно простой — указание ошибки уже в нем было. Кроме того, в диалоговое окно поместилось только 3200 знаков, при том что полный стек-трейс содержит 32 000. 

Продолжаем анализировать логи, после чего выявим несколько следствий:

  • Чем меньше в стек-трейсе явных указаний на ошибку, тем более общий неконкретный и бесполезный ответ даст нейросеть. 

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

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 4

В первом ответе ошибка никак не связана с кэшем, в логе об этом вообще не было сказано, однако рассуждения о кэше и о запросах select были подтянуты из других, не относящихся к данной ошибке логов. 

Во втором ответе из «чистого» диалога нет конкретики, но в целом суть происходящего передана верно.

Совет: если анализируете много ошибок, почаще обновляйте диалог, особенно, если ошибки разнородные. 

Создание отчетности о тестировании

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

Для проверки возможности генерации отчета тестирования в «закромах» нашелся старый чек-лист о тестировании одного pet-проекта. В нем есть таблица с номерами, приоритетами, названиями и статусам прохождения проверок. Все это было превращено в CSV и отправлено в один из чат-ботов с запросом: 

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 5

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

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 6
ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 7

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

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 8

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

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 9

Здесь есть явные проблемы. И дело не в том, что диаграмма не очень «красивая», а в том, что статусы подсчитаны неверно. В представленном файле в статусе «пройдено» — 20 кейсов, а не 24; в статусе «пройдено с багом» — 7 проверок, а не 9. Всего в файле 28 кейсов, а не 35. Интересно, что 35 — это общее количество строк в файле. 

Эксперименты в других чат-ботах по созданию отчета о тестировании на основе файла дали схожие результаты. Общий вывод такой: обзорный отчет «по верхам» нейросеть делает хорошо, но чем дальше углубляться и просить больше значимых деталей, тем больше ИИ спотыкается. 

ИИ в автоматизации тестирования (написании автотестов)

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

Если Chat GPT попросить написать автотест на Java для проверки отправки POST-запроса с сериализацией данных класса в тело запроса, то ответ будет примерно таким:

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 10

Код подробно задокументирован и выглядит неплохо. Стоит отметить, что использование 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 или нет.

Ответ:

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 11

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

ИИ в тестировании ПО: возможности, ограничения, эксперименты и практический опыт - 12

Компактная функция, но меня сразу смутил 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.

Автор: SSul

Источник

Rambler's Top100