Методология генерации случайных строк посредством регулярных выражений

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет, Хабр!

Если ваш проект вырос, в нем бэкенд с фронтендом, различные точки входа API, интеграции с внешними системами, сложные алгоритмы, проверки введенных данных пользователем на валидность, диаграммы бизнес-процессов имеют тысячи ветвей, то скорее всего регрессионное тестирование занимает кучу времени, и проводить его вручную уже невыгодно. Проще эту работу поручить машине и тестировать продукт автоматически.  Первый вопрос, который возникает — «Как генерировать данные?», а конкретнее, как генерировать то, что может ввести пользователь. Этот вопрос мы и разберем в данной статье.

Обычно введенные строки сравнивают с некими шаблонами, среди которых наиболее распространенный– RegExr (регулярное выражение). Самый логичный способ — тестировать шаблон шаблоном.

Что такое и из чего состоит RegExr:

RegExr — шаблон, в котором представлена совокупность правил для конкретных позиций в строке.

Для единичных символов понятно, на этой позиции может быть только он. А в квадратных скобках указаны возможные варианты символов, например [1-9#] на этой позиции возможны только символы — 123456789#, а для правила [^@\.]  возможны любые символы кроме @ и . (напомню, что символ ^ после открывающей скобки означает «кроме»)

Квантификатор даёт нам информацию о том, на сколько позиций распространяется символ или символьная группа перед ним.

Квантификатор

Использование

{n}

Ровно n повторений

{m,n}

От m до n повторений

{m,}

Не менее m повторений

{,n}

Не более n повторений

?

Ноль или одно повторение

То же, что и {0,1}

*

Ноль или более повторений

То же, что и {0,}

+

Одно или более повторений

То же, что и {1,}

 

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

Логика “или” позволяет сделать наше выражение более эластичным. В примере строка может состоять либо из 6 цифр, либо из 10. Выражений разделенных элементом | может быть  сколько угодно, но на этом месте может быть только одно из них.

Проблематика:

Например, поле email не принимает случайный набор символов, естественно там присутствует проверка через регулярное выражение, и в самом простом виде это [^@]+@([^@\.]+\.)+[^@\.]+. Соответственно, нам нужно либо захардкодить значение на каждое поле, либо при каждом тесте генерировать строку, которая подойдет под это выражение.
Чем обернется хардкод: 

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

2.       Возникает риск ошибки, ведь по основному принципу тестирования мы тестируем черный ящик и не знаем какое там регулярное выражение, так как программист мог спокойно указать [^@]+@[^@\.]+\.[^@\.]+, и misha@mail.ru пройдет, а diana@inform.bigdata.ru нет.

3.       Банально под ваши тесты могут подогнать регулярное выражение :)

Соответственно, правильно будет каждый раз генерировать новую случайную строку. Рекомендую писать свое регулярное выражение для генерации, основываясь на ТЗ, а не таскать их из кода.  Для того, чтобы сгенерировать случайную строку, нужно решить две основные проблемы:

1.       Какие рамки поставить для квантификаторов +, {m,}, *. Ведь бесконечное количество символов мы сгенерировать не можем, а строка из тысячи символов только нагрузит интерфейс и особо никак не повлияет на тестирование. Тут нужно найти баланс и случайно не написать стресс-тест.

2.       Откуда брать символы для генерации такого выражения — [^@\.]? Из таблицы ASCI? Но там довольно много специальных символов, и в итоге мы получим непонятную кашу.

Ответив на эти вопросы, мы сможем реализовать генерацию. Первый вопрос решается выбором верхней планки длины строки или квантификатора, например 50 символов. А второй — собственной библиотекой символов для проекта.

Задача:

Для генерации строки из выражения нужно разложить его на такие части, которые будет принимать конечный  автомат. То есть нужно привести к такому виду, что некая функция будет принимать его части на вход (множество символов B), выбирать такой символ a, который принадлежит этому множеству и выдавать этот символ.

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

Приведу свою блок-схему алгоритма генерации включающую в себя 5 основных этапов:

1 Этап — декомпозиция основного выражения на подгруппы:

2 Этап — выбор между возможными вариантами:

Для оптимизации времени выполнения алгоритма, этот этап выполняется сразу после декомпозиции и позволяет не тратить времени на генерацию ненужных символов.

3 Этап — обработка символьных групп:

На этапе происходит замена шаблонов и формирование множеств для конечных автоматов.

4 Этап — обработка квантификаторов:

На этом этапе нам требуется выбрать конкретные значения для квантификаторов. Тут мы сталкиваемся с проблемой описанной ранее, квантификаторы +, *, {n,} представляют диапазоны чисел от n до бесконечности, с такими диапазонами мы работать не можем, поэтому требуется ограничение, например от n до n + 50. Потом для диапазонов нам нужно выбрать конкретное значение, оно и будет означать количество запусков конечных автоматов.  Далее мы «разворачиваем» выражения в круглых скобках в зависимости от значения их квантификатора.

Отмечу, что мы должны рекурсивно запускать алгоритм для каждой группы столько раз, сколько указано в её квантификаторе.

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

5 Этап — Запуск конечных автоматов.

После всех этих этапов мы получаем общность конечных автоматов, которые и требуется запустить:

Зачем изобретать велосипед?

Увы, но нет универсальных решений, и под свои задачи нужно либо модифицировать, либо писать что-то самостоятельно. Например, на нашем проекте для автоматического тестирования API был выбран язык Python. Он простой, удобный, и обучение специалиста, который сможет поддерживать фреймворк — дело буквально месяца-двух.  У нас несколько требований к библиотеке генерации случайных строк:

1.       Быстрая;

2.       Удобная;

3.       Должна поддерживать основную лексику регулярных выражений;

4.       В начале и конце сгенерированной строки не должно быть пробелов

В своих поисках мы нашли 4 библиотеки: xeger, strgen, exrex, rstr.

Strgen – самая быстрая, практически идеальна, но не поддерживает многие квантификаторы.

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

Rstr — Не самая стабильная библиотека, в некоторых моментах работает в 5 раз медленнее других.

Exrex — генерирует 1000 случайных строк в среднем за 2 секунды, не критично, но можно лучше.

Хотелось бы получить универсальную, быструю библиотеку, подходящую под наши требования. Вот так и появилась на свет библиотека re_generate (pypi.org/project/re-generate). Получилось даже лучше, чем мы думали, уже до оптимизации алгоритм выдает хорошие показатели в сравнительных бенчмарках:

Итог:

Если вы не нашли уже готового решения для вашего проекта, рекомендуем реализовать этот алгоритм, таким образом вы получите практику и прекрасный инструмент для работы. Забирайте в свои проекты, пользуйтесь, реализуйте. Спасибо за внимание!

 

 

 

 

 

Источник: https://habr.com/ru/company/ppr/blog/710836/


Интересные статьи

Интересные статьи

На данный момент уведомления являются одним из основных инструментов маркетинга. Они позволяют бизнесу не только удерживать интерес пользователя к продукту, но и поддерживать лояльность, показывая пол...
Сегодня мы поговорим о том, зачем учить операционную систему GNU/Linux, о преимуществах работы в командной строке и о том, как это все связано с философией Unix. Это не п...
Привет Хабр! Меня зовут Когунь Андрей. В КРОК я руковожу группой разработчиков Java (у нас большая распределённая по всей стране команда). Ещё я провожу встречи московского сообщества...
Привет, Хабр! В этой публикации я расскажу о статье автора Jinmo Kim: "Maze Terrain Authoring System in Immersive Virtual Reality for New Visual Realism". Она была опубликована 4.04.2019. Полны...
Приложения, размещенные в строке меню, уже давно известны пользователям macOS. У некоторых из этих приложений есть «обычная» часть, другие размещены только в строке меню. В этом руководстве вы н...