Как мы использовали нейросети для генерации тестовых данных

от автора

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

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

Также нейросети могут быть эффективно применены в различных задачах тестирования приложений, включая:

  • Автоматизацию тестирования – могут быть обучены находить дефекты и ошибки в приложениях, что значительно ускоряет процесс тестирования,

  • Тестирование на основе изображений – приложений с GUI могут использоваться для детекции визуальных изменений и сравнения скриншотов,

  • Тестирование на основе данных пользовательского поведения – могут анализировать данные о поведении пользователей, выявлять нестандартные сценарии использования и помогать в их тестировании.

О задаче

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

Так вот, наша команда в ICL Soft разрабатывает клиент-серверное приложение с web-клиентом и мобильным приложением. Мобильное приложение предназначается для полевых сотрудников, а потому может функционировать в офлайн-режиме. Как следствие, приложение имеет свою базу данных и сильно зависит от данных.

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

Наше приложение содержало более 20 справочников и несколько десятков различных сущностей, но чтобы было проще объяснить подход по генерации данных, мы упростим задачу только до генерации списка врачей (приложение из фармацевтической отрасли). По составу полей сущности врач для упрощения будем полагать, что нам нужны:

  1. Идентификатор

  2. ФИО

  3. Дата рождения

  4. Стаж

На самом деле, полей гораздо больше, но нам важны они, а принципы работы с полями, там где можно сгенерировать значения для 4х полей, там же можно сделать это для 50 или 100 полей.

Итерация №1: Как все начиналось

Отмечу, что СУБД подразумевает хранение в JSON-формате, в случае если у вас обычные реляционные таблицы, то вместо JSON вам нужно получать на выходе SQL запросы с INSERT запросами, но суть остается прежней.

Первое и самое очевидное действие любого тестировщика – попросить ChatGPT или аналогичную LLM сгенерировать JSON с перечнем врачей. О том, как правильно писать запросы для LLM, можно узнать тут.

Например, берем такой запрос: «Как оператор данных, сгенерируй список из 5 людей в JSON формате с полями id в формате guid, FIO в формате Фамилия Имя Отчество, birthday в формате даты с возрастом от 23 до 45 лет, years_exp стаж в годах от 3 до 15 лет»

Диапазоны возможных значений приведены «на шару» для упрощения, по факту же работа тестировщика начинается уже с того, что нужно правильно сформулировать запрос, правильно отобрать возможные значения (в т. ч. граничные значения), учесть возможные зависимости, форматы и т.д.

Отправив данный запрос, например, в GPT-like нейросети (в нашем случае Theb AI) будет получен ответ, например такой:

[

    {

        «id»: «42e8d9e1-12cf-4e2e-b953-b672737c3c24»,

        «FIO»: «Иванов Иван Иванович»,

        «birthday»: «1980-05-20»,

        «years_exp»: 10

    },

    {

        «id»: «fa34be8e-5175-4820-adfc-fd0c5042cd54»,

        «FIO»: «Петров Петр Петрович»,

        «birthday»: «1978-03-15»,

        «years_exp»: 8

    },

    {

        «id»: «b6de8974-1e39-4bb7-90cf-d42e573aa0c2»,

        «FIO»: «Сидоров Александр Иванович»,

        «birthday»: «1975-11-30»,

        «years_exp»: 15

    },

    {

        «id»: «76906c6f-71c0-4937-aa41-99467cdc9d88»,

        «FIO»: «Козлова Ольга Петровна»,

        «birthday»: «1999-08-10»,

        «years_exp»: 3

    },

    {

        «id»: «8b27ea14-5c5f-4b16-9c8c-5a828f305bdf»,

        «FIO»: «Беляева Екатерина Николаевна»,

        «birthday»: «1995-12-25»,

        «years_exp»: 5

    }

]

 

С точки зрения формата и данных вроде бы все устраивает, но, а что если вам нужно сгенерировать не 5 строк, а 200? А если 10000, или вовсе миллион? И здесь мы столкнемся с ограничениями на длину ответа.

Так, например, при запросе на 100 человек «как оператор данных сгенерируй список из 100 людей в JSON формате с полями id в формате guid, FIO в формате Фамилия Имя Отчество, birthday в формате даты с возрастом от 23 до 45 лет, years_exp стаж в годах от 3 до 15 лет» , мы уже получим это:

[

    {

        «id»: «01234567-89ab-cdef-0123-456789abcdef»,

        «FIO»: «Иванов Иван Иванович»,

        «birthday»: «1980-05-20»,

        «years_exp»: 10

    },

    {

        «id»: «12345678-9abc-def0-1234-56789abcdef0»,

        «FIO»: «Петров Петр Петрович»,

        «birthday»: «1978-09-15»,

        «years_exp»: 5

    },

    {

        «id»: «23456789-abcd-ef01-2345-6789abcdef01»,

        «FIO»: «Сидоров Сергей Николаевич»,

        «birthday»: «1985-02-10»,

        «years_exp»: 8

    },

    // и так далее…

]

Причем комментарий «//и так далее…» – это не текст для сокращения листинга статьи, а именно обратная связь от нейросети.

Например, в ChatGPT 3.5 ограничение на количество токенов в одном запросе на ответ составляет примерно 4096 токенов. В случае, если введенный текст превышает это количество, модель может выдать сообщение об ошибке или обрезать входные данные. Это ничтожно мало для того, чтобы заполнить СУБД данными.

Первое что приходит на ум — генерировать пользователей, через API, никто же не мешает вызвать успешный запрос выше 10000 раз.

Но имеется и другая проблема с большинством облачных GPT — за них нужно платить. В том же ChatGPT 3.5 платить нужно за каждый токен и генерация нескольких мегабайт данный будет уже стоить значимую сумму.

Итерация №2: Решаем проблему со стоимостью и длинной ответа

Изучив итерацию №1, вы уже наверняка поняли, как можно работать с GPT, но это еще не то, что нам нужно, чтобы решить вопрос со стоимостью и длинной ответа.

Решение на самом деле очень простое – нужно просить генерировать не непосредственно данные, а попросить GPT написать скрипт, который уже будет генерировать, то что вам нужно.

Для этого запрос выше преобразуем в запрос вида: «Как программист напиши скрипт на Python, который сгенерирует список из 100 людей в JSON формате с полями id в формате guid, FIO в формате Фамилия Имя Отчество, birthday в формате даты с возрастом от 23 до 45 лет, years_exp стаж в годах от 3 до 15 лет»

На выходе мы увидим, например, такой ответ:

import json

import uuid

import random

from datetime import datetime, timedelta

 

def generate_fio():

    first_names = [‘Иван’, ‘Мария’, ‘Александр’, ‘Елена’, ‘Сергей’, ‘Ольга’, ‘Дмитрий’, ‘Наталья’]

    last_names = [‘Иванов’, ‘Петров’, ‘Сидоров’, ‘Козлов’, ‘Смирнов’, ‘Лебедева’, ‘Кузнецова’, ‘Орлова’]

   

    return f'{random.choice(last_names)} {random.choice(first_names)} {random.choice(first_names)}’

 

def generate_birthday_and_age():

    end_date = datetime.now() — timedelta(days=45*365)  # старше 45 лет

    start_date = end_date — timedelta(days=22*365)  # младше 23 лет

    birthday = start_date + (end_date — start_date) * random.random()

    age = int((datetime.now() — birthday).days / 365.25)

    return birthday.strftime(‘%Y-%m-%d’), age

 

people = []

 

for _ in range(100):

    person = {

        ‘id’: str(uuid.uuid4()),

        ‘FIO’: generate_fio(),

        ‘birthday’: generate_birthday_and_age()[0],

        ‘years_exp’: random.randint(3, 15)

    }

    people.append(person)

 

json_data = json.dumps(people, ensure_ascii=False, indent=4)

 

with open(‘people.json’, ‘w’, encoding=’utf-8′) as f:

    f.write(json_data)

 

print(«Сгенерированные данные сохранены в people.json файле.»)

 

Мы видим рабочий скрипт или почти рабочий скрипт (как повезет), который генерирует действительно 100 человек, как мы попросили. Но внимательный читатель обратит внимание на ряд недочетов: например, на то, что список имен ограничен списком из массива и т. д.

Доработаем запрос: «Как программист напиши скрипт на Python, который сгенерирует список из 100 людей в JSON формате с полями id в формате guid, FIO в формате Фамилия Имя Отчество, birthday в формате даты с возрастом от 23 до 45 лет, years_exp стаж в годах от 3 до 15 лет. Загрузка FIO должна осуществляться из файла”

На выходе получаем ответ:

import json

import uuid

import random

from datetime import datetime, timedelta

 

# Функция для чтения ФИО из файла

def load_names(file_path):

    with open(file_path, ‘r’, encoding=’utf-8′) as file:

        names = [line.strip() for line in file]

    return names

 

# Функция для генерации даты рождения на основе возраста

def generate_birthday(min_age, max_age):

    today = datetime.today()

    min_date = today — timedelta(days=max_age*365)

    max_date = today — timedelta(days=min_age*365)

    random_date = min_date + (max_date — min_date) * random.random()

    return random_date.strftime(‘%Y-%m-%d’)

 

# Чтение ФИО из файла

names = load_names(‘fio.txt’)

 

# Генерация списка людей

people = []

for _ in range(100):

    person = {

        ‘id’: str(uuid.uuid4()),

        ‘FIO’: random.choice(names),

        ‘birthday’: generate_birthday(23, 45),

        ‘years_exp’: random.randint(3, 15)

    }

    people.append(person)

 

# Сохранение списка людей в JSON файл

with open(‘people.json’, ‘w’, encoding=’utf-8′) as file:

    json.dump(people, file, ensure_ascii=False, indent=4)

 

print(‘Генерация списка людей завершена!’)

Файл со списком возможных ФИО можно подготовить с помощью того же GPT. Ну, думаю, принцип понятен: теперь вы уже можете для простых проектов подготовить данные быстрее, чем если бы вы писали скрипты совсем без навыков в скриптинге – там будет сложно, но можно.

Итерация №3. Нет предела совершенству

Итерации №2 не хватит опять-таки для сложных проектов, либо займет много времени. При наличии навыков можно пойти дальше генерировать запросы по структуре СУБД, которые потом передавать GPT для генерации соответствующих скриптов с учетом зависимостей между сущностями. При этом важно выстроить иерархию данных, и в первую очередь генерировать сущности, которые не зависят от других сущностей и справочники, затем генерировать сущности, которые будут использовать значения из уже сгенерированных сущностей и т.д.  Я бы посоветовал сразу выстраивать цепочки вызовов скриптов, т. к. не стоит рассчитывать, что достаточно будет одного полного цикла для генерации данных для СУБД. Однозначно будут недочеты и ошибки выполнения, которые потребуют анализа и корректировок.

И это всего лишь один из рабочих вариантов использования GPT. А теперь можно снова посмотреть на мем в начале статьи: уверен, он заиграет новыми красками!

Выводы

В целом может показаться, что проще сразу написать скрипт, который все сгенерирует – но при некотором опыте общения с GPT и небольшом опыте в скриптинге, экономия по сравнению с 100% кодингом может составлять десятки раз. Тренируйтесь и набивайте руку, нарабатывайте опыт, и у вас обязательно все получится.

Для себя с командой сделали следующие выводы:

  • Использование нейросетей в подготовке данных для тестирования приносит значительную пользу.

  • Опыт взаимодействие тестировщика с нейросетями (и с GPT частности) играет ключевую роль в оптимизации результатов.

  • Совсем без знаний скриптинга обойтись не получится.

  • Понимание возможностей и ограничений нейросетей с умением взаимодействовать с ними наилучшим образом способствует достижению высоких результатов.


ссылка на оригинал статьи https://habr.com/ru/articles/825726/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *