Как разработчики или тестировщики, мы часто сталкиваемся с необходимостью тестирования наших систем. В этом процессе, будь то модульное тестирование, интеграционное тестирование или любая другая форма тестирования, данные часто являются ведущим и решающим фактором.
Но получить доступ к хорошим тестовым данным не всегда просто. Иногда данные являются весьма конфиденциальными, например, медицинские или финансовые данные. В других случаях данных недостаточно (например, при попытке нагрузочного тестирования), а иногда искомые данные трудно найти. Для случаев, подобных описанному выше, есть решение называемое Datafaker.
Datafaker — это библиотека для JVM, предназначенная для генерации фиктивных данных, похожих на производственные данные.
Эти данные могут быть сгенерированы как часть ваших модульных тестов или могут быть сгенерированы в виде внешних файлов, таких как файлы CSV или JSON, чтобы они могли служить в качестве входных данных для других систем.
В этой статье вы узнаете, что такое Datafaker, что он может делать и как его можно эффективно использовать для улучшения стратегии тестирования.
Что такое Datafaker?
Datafaker — это библиотека, написанная на Java, которая может использоваться в популярных языках JVM, таких, как Java, Kotlin или Groovy. Ее разработка начиналась как форк больше не поддерживаемого Javafaker, но с момента ее создания она претерпела множество улучшений. Datafaker состоит из ядра, управляющего генерацией данных, а поверх него имеется широкий спектр провайдеров данных, специфичных для конкретной области. Такие провайдеры могут быть очень полезными, например, для генерации реальных адресов, имен, номеров телефонов, кредитных карт и других данных, а иногда они могут быть более легковесными, например, при создании персонажей телешоу Friends или IT Crowd. Независимо от вашего сценария использования, существует большая вероятность того, что Datafaker сможет предоставить данные для вашего приложения. А если есть доступный поставщик данных, Datafaker предоставляет возможность подключаемой системы для создания ваших собственных поставщиков!
Как использовать Datafaker
Datafaker регулярно публикует обновления в Maven Central, поэтому самый простой способ начать работу с Datafaker — использовать инструмент управления зависимостями, такой как Maven или Gradle. Чтобы начать работу с Datafaker с помощью Maven, вы можете включить зависимость следующим образом:
<dependency>
<groupId>net.datafaker</groupId>
<artifactId>datafaker</artifactId>
<version>1.4.0</version>
</dependency>
Выше мы используем версию 1.4.0, последнюю версию на момент написания этой статьи. Чтобы убедиться, что вы используете последнюю версию, проверьте Maven Central.
После включения библиотеки в ваш проект проще всего генерировать данные следующим образом:
import net.datafaker.Faker;
Faker faker = new Faker();
System.out.println(faker.name().fullName()); // Printed Vicky Nolan
Если вам нужна дополнительная информация, в документации Datafaker есть отличное руководство по началу работы с Datafaker.
Происходит несколько вещей, которые, возможно, не сразу заметны. Например, каждый раз, когда вы запускаете приведенный выше код, он будет выводить случайное полное имя, состоящее из имени и фамилии. Каждый раз это имя будет разным.
В нашем примере выше используется локаль по умолчанию (English) и случайное начальное значение, что означает, что случайное имя будет генерироваться каждый раз, когда вы запускаете приведенный выше код.
Но если мы хотим что-то более предсказуемое и, возможно, использовать другой язык, мы можем:
long seed = 1;
Faker faker = new Faker(new Locale("nl"), new Random(seed));
System.out.println(faker.name().fullName());
В приведенном выше примере мы генерируем случайное голландское полное имя, но, поскольку сейчас мы используем фиксированное начальное число, мы знаем, что независимо от того, как часто мы запускаем наш код, программа будет выдавать одни и те же случайные значения при каждом запуске.
Это очень помогает, если мы хотим, чтобы наши тестовые данные были немного более повторяемыми, например, когда мы проводим регрессионное тестирование.
Хотя в приведенном выше примере показано, как генерировать имена, можно генерировать очень широкий спектр случайных данных. Например, адреса, номера телефонов, кредитные карты, цвета, коды и т. д. Полный список этих данных можно найти в документации (https://www.datafaker.net/documentation/providers/). Кроме того, Datafaker также предоставляет дополнительные технические возможности, такие как случайные перечисления и списки, чтобы облегчить генерацию случайных тестовых данных.
Пользовательские коллекции
Если вам необходимо сгенерировать больший набор тестовых данных, Datafaker предоставляет несколько вариантов для этого. Одним из таких вариантов является использование фиктивных коллекций. Фиктивные коллекции позволяют создавать большие наборы данных в памяти, предоставляя набор данных поставщиков для метода коллекции. Это лучше всего продемонстрировать на примере:
List<String> names = faker.<String>collection()
.suppliers(
() -> faker.name().firstName(),
() -> faker.name().lastName())
.minLen(5)
.maxLen(10)
.build().get();
Приведенный выше код создаст коллекцию строк с числом элементов от 5 до 10. Каждый элемент будет либо именем, либо фамилией. Можно создать множество вариаций приведенного выше примера, и подобные примеры возможны, даже при разных типах данных:
List<Object> data = faker.collection()
.suppliers(
() -> faker.date().future(10, TimeUnit.DAYS),
() -> faker.medical().hospitalName(),
() -> faker.number().numberBetween(10, 50))
.minLen(5)
.maxLen(10)
.build().get();
System.out.println(data);
Этот код сгенерирует список объектов, поскольку генераторы 'Future', 'HospitalName' и 'NumberBetween' имеют разные типы возвращаемых данных.
Пользовательские провайдеры
Хотя Datafaker предоставляет множество готовых генераторов, может оказаться, что генераторы отсутствуют или некоторые из них работают немного иначе, чем требуется в вашем случае. Для поддержки подобных случаев можно создать свой собственный поставщик данных, либо предоставив YML файл конфигурации, либо жестко запрограммировав возможные значения в коде.
Чтобы создать поставщика данных, необходимо выполнить два шага: создать поставщика данных и зарегистрировать поставщика данных в вашем пользовательском классе типа Faker. Ниже приведен пример, в котором мы создадим специальный провайдер для генерации имен черепах:
class Turtle {
private static final String[] TURTLE_NAMES = new String[]{"Leonardo", "Raphael", "Donatello", "Michelangelo"};
private final Faker faker;
public Turtle(Faker faker) {
this.faker = faker;
}
public String name() {
return TURTLE_NAMES[faker.random().nextInt(TURTLE_NAMES.length)];
}
}
Поскольку все методы доступа к провайдерам в классе Faker являются статическими, нам нужно создать собственный класс Faker, который расширит исходный класс Faker, чтобы мы могли использовать все существующие провайдеры данных, а также наши собственные:
class MyCustomFaker extends Faker {
public Turtle turtle() {
return getProvider(Turtle.class, () -> new Turtle(this));
}
}
Использование пользовательского класс Faker похоже на то, что мы видели раньше:
MyCustomFaker faker = new MyCustomFaker();
System.out.println(faker.turtle().name());
Если вы хотите узнать больше о создании собственного провайдера или использовании YML-файлов для предоставления данных, документация по пользовательским провайдерам данных Datafaker содержит дополнительную информацию на эту тему.
Экспорт данных
Иногда вам требуется не только сгенерировать данные в памяти, но и предоставлять их внешней программе. Обычно для этого используется предоставление данных в файлах CSV.
Datafaker предоставляет такую функцию «из коробки», и помимо генерации файлов CSV, он также имеет возможность генерировать файлы JSON, YML или XML без необходимости использования внешних библиотек. Создание таких данных аналогично созданию коллекций данных, которые мы рассмотрели выше.
Генерация файлов может быть выполнена несколькими способами. Например, иногда требуется сгенерировать документ со случайными данными. Для этого, чтобы сгенерировать CSV-файл со случайными данными, используйте метод toCsv класса Format. Пример можно найти ниже:
System.out.println(
Format.toCsv(
Csv.Column.of("first_name", () -> faker.name().firstName()),
Csv.Column.of("last_name", () -> faker.name().lastName()),
Csv.Column.of("address", () -> faker.address().streetAddress()))
.header(true)
.separator(",")
.limit(5).build().get());
В приведенном выше примере генерируются 5 строк данных, и каждая строка состоит из имени, фамилии и почтового адреса. Можно настроить генерацию CSV, например, включив или исключив заголовок, или используя другой символ разделитель. Более подробную информацию о различных вариантах и примеры создания файлов XML, YML или JSON можно найти в документации по форматам файлов Datafaker.
Экспорт данных с некоторыми ограничениями
Существует еще один способ генерации CSV. Так называемая условная генерация, когда между данными существуют некоторые ограничения. Представьте, что мы хотим сгенерировать документ, содержащий имя человека и его/ее интересы, а также выборку интересов.
Для простоты мы рассмотрим 2 области интересов: Музыка и Еда. Для «Музыки» мы хотим увидеть образец музыкального жанра, для «Еды» мы хотим увидеть образец блюда, например.
"name";"field";"sample"
"Le Ferry";"Music";"Funk"
"Mrs. Florentino Schuster";"Food";"Scotch Eggs"
Для этого нам нужно сгенерировать коллекцию таких данных.
Сначала создадим правила для генерации объектов, например:
class Data {
private Faker faker = new Faker();
private String name;
private String field;
private String interestSample;
public Data() {
name = faker.name().name();
field = faker.options().option("Music", "Food");
switch (field) {
case "Music": interestSample = faker.music().genre(); break;
case "Food": interestSample = faker.food().dish(); break;
}
}
public String getName() {
return name;
}
public String getField() {
return field;
}
public String getInterestSample() {
return interestSample;
}
}
Теперь мы можем использовать класс Data для генерации данных CSV, как показано ниже:
String csv = Format.toCsv(
new Faker().<Data>collection()
.suppliers(Data::new)
.maxLen(10)
.build())
.headers(() -> "name", () -> "field", () -> "sample")
.columns(Data::getName, Data::getField, Data::getInterestSample)
.separator(";")
.header(true)
.build().get();
Этот код сгенерирует строку CSV с заголовками и столбцами, содержащими случайные данные, но с ограничениями между указанными нами столбцами.
Заключение
В этой статье был дан обзор некоторых возможностей, предоставляемых Datafaker, и того, как Datafaker может помочь вам в решении ваших задач тестирования.
Если у вас есть предложения, сообщения об ошибках или или другие замечания, зайдите на сайт проекта Datafaker. И не стесняйтесь оставлять свои отзывы.