EasyRandom — это библиотека Java, которая позволяет разработчикам легко генерировать случайные объекты, которые могут быть полезны для тестирования, прототипирования и заполнения данных. Это мощный инструмент, который может сэкономить время и усилия при работе с объектно-ориентированными языками программирования, такими как Java.

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

Вот вопрос к вам, какой фрагмент кода вы предпочитаете:

1.

Street street = new Street(12, (byte) 1, "Oxford street");
Address address = new Address(street, "123456", "London", "United Kingdom");
Person person = new Person("Foo", "Bar", "[email protected]", Gender.MALE, address);

2.

EasyRandom easyRandom = new EasyRandom();
Person person = easyRandom.nextObject(Person.class);

3.

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

Начало работы с EasyRandom

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

Настройка EasyRandom

Сначала требуется добавить зависимость EasyRandom в ваш проект. Вы можете сделать это, добавив следующий код в файл build.gradle:

dependencies {
    testImplementation 'org.jeasy:easy-random-core:5.0.0'
}

После добавления зависимости вы можете использовать EasyRandom в своих тестах.

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

Допустим, у вас есть простой класс User:

public class User {
    private String email;
    private String firstName;
    private String lastName;

    // Getters and setters omitted for brevity
}

Чтобы сгенерировать случайный объект пользователя, вы можете использовать EasyRandom следующим образом:

EasyRandom easyRandom = new EasyRandom();
User user = easyRandom.nextObject(User.class);

Это создаст случайный объект User со случайными значениями для электронной почты, firstName и lastName.

Давайте проверим это в нашем тестовом примере:

@Test
void shouldGenerateUserWithFilledFields(){
//given
     EasyRandom easyRandom = new EasyRandom();
     //when
     User user = easyRandom.nextObject(User.class);
     //then
     assertThat(user.getEmail()).isNotEmpty();
     assertThat(user.getFirstName()).isNotEmpty();
     assertThat(user.getLastName()).isNotEmpty();
     // preview
     System.out.println(user.toString());
}

Напечатанный пользователь:

User{
email='eOMtThyhVNLWUZNRcBaQKxI', firstName='yedUsFwdkelQbxeTeQOvaScfqIOOmaa', lastName='JxkyvRnL'
}

Создание коллекций и карт

Коллекции как поля

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

@Getter
@Builder
public class User2 {
 private String email;
 private String firstName;
 private String lastName;
 private List<Book> books;
 private Map<Long, Book> someMap;
}

Наш тестовый пример:

@Test
void shouldGenerateCollectionFields(){
     //given
     EasyRandom easyRandom = new EasyRandom();
     //when
     User2 user = easyRandom.nextObject(User2.class);
     //then
     assertThat(user.getEmail()).isNotNull();
     assertThat(user.getFirstName()).isNotNull();
     assertThat(user.getLastName()).isNotNull();

     assertThat(user.getBooks()).isNotNull();
     assertThat(user.getBooks()).allMatch(book -> !book.getAuthor().isEmpty());

     assertThat(user.getSomeMap()).isNotNull();
     assertThat(user.getSomeMap().values()).extracting(Book::getAuthor).allMatch(author -> !author.isEmpty());

     // preview
     System.out.println(user.toString());
}

Напечатано пользователем2:

User2{
email='eOMtThyhVNLWUZNRcBaQKxI',
firstName='yedUsFwdkelQbxeTeQOvaScfqIOOmaa',
lastName='JxkyvRnL',
books=[Book{
 title='RYtGKbgicZaHCBRQDSx',
 author='VLhpfQGTMDYpsBZxvfBoeygjb',
  isbn='UMaAIKKIkknjWEXJUfPxxQHeWKEJ'},
  ...
 ],
someMap={
 -5237980416576129062=Book{
         title='RYtGKbgicZaHCBRQDSx',
         author='VLhpfQGTMDYpsBZxvfBoeygjb',
          isbn='UMaAIKKIkknjWEXJUfPxxQHeWKEJ'},
  ...
  }
}

Коллекции простых данных

Мы можем создавать коллекции, используя предоставленные EasyRandom методы, возвращающие потоки.

В этом примере мы можем сгенерировать список лонгов заданного размера.

@Test
void generateCollectionsOfSimpleDataWithSize(){
     List<Long> longs = new EasyRandom()
.longs(streamSize:10)
.boxed()
.toList();

     assertThat(longs.size()).isEqualTo(10);
     System.out.println(longs);
}

Печатные значения:

[-5106534569952410475, -167885730524958550, 4672433029010564658, -7216359497931550918, -3581075550420886390, -2298228485105199876, -5237980416576129062, 1326634973105178603, -3758321679654915806, -7771300887898959616]

Кроме того, мы можем сгенерировать список с указанными размерами и границами.

@Test
void generateCollectionOfSimpleDataWithSizeAndBouds(){
     List<Long> longs = new EasyRandom()
             .longs(streamSize:20,
randomNumberOrigin:13,
randomNumberBound:51)
             .boxed()
             .toList();

     assertThat(longs.size()).isEqualTo(20);
     assertThat(longs).allMatch(l->l>=13 && l<=51);
     System.out.println(longs);
}

Печатные значения:

[23, 28, 30, 30, 24, 25, 46, 28, 14, 23, 38, 17, 30, 45, 45, 29, 48, 48, 15, 45]

Коллекции объектов

EasyRandom без проблем генерирует список объектов. Подобным образом:

@Test
void shouldGenerateListOfUsers(){
     List<User2> users = new EasyRandom()
.objects(User2.class, streamSize:5)
.toList();

     assertThat(users.size()).isEqualTo(5);
     assertThat(users).allMatch(user -> !user.getEmail().isEmpty())
             .allMatch(user-> !user.getFirstName().isEmpty());
}

Особые случаи

Ограничения на поля

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

public class User3 {

 @Email
 private String email;

 @Size(min = 3, max = 5)
 private String firstName;
}

Наш тест провалится, потому что мы все еще генерируем случайные поля.

@Test
void shouldGenerateProperFields(){
     //given
     EasyRandom easyRandom = new EasyRandom();
     //when
     User3 user = easyRandom.nextObject(User3.class);
     //then
     System.out.println(user.toString());
     assertThat(user.getEmail()).isNotNull();
     assertThat(user.getFirstName().length()).isBetween(3,5);
}

Печатный текст:

User3{email='eOMtThyhVNLWUZNRcBaQKxI', firstName='yedUsFwdkelQbxeTeQOvaScfqIOOmaa'}

Мы можем легко исправить это, добавив наш собственный рандомизатор!

public class EmailRandomizer implements Randomizer<String> {
 public String getRandomValue() {
     // generate a random alphanumeric string of length 10 for the username part of the email address
     String username = RandomStringUtils
             .randomAlphanumeric(10);
     // generate a random top-level domain from a list of popular ones
     String[] tlds = {"com", "net", "org", "gov", "edu"};
     String tld = tlds[new Random().nextInt(tlds.length)];
     // return the random email address
     return username + "@" + tld;
 }
}

Мы можем использовать его, предоставив его в EasyRandomParameters, который затем мы будем использовать с конструктором EasyRandom.

@Test
void shouldGenerateUserWithProperFields(){
//when
     User3 user = randomUser3();
     //then
     assertThat(user.getEmail()).isNotNull().contains("@");
     assertThat(user.getFirstName().length()).isBetween(3,5);
     // preview
     System.out.println(user.toString());
}

private User3 randomUser3(){
     EasyRandomParameters parameters = new EasyRandomParameters()
             .randomize(field->
                     field.getName().equals("email"),
                     new EmailRandomizer())
             .randomize(field->
                     field.getName().equals("firstName"),
                     new StringRandomizer(
minLength: 3,
maxLength: 5,
      seed: 10));
     EasyRandom easyRandom = new EasyRandom(parameters);
     return easyRandom.nextObject(User3.class);
}

Печатный текст:

User3{email='r3WATL5Ifh@net', firstName='pgly'}

Рандомайзеры

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

Рекорды

В настоящее время (апрель 2023 г.) библиотека EasyRandom не поддерживает записи. Запросы на слияние добавляют эту функциональность, но ожидают слияния. Однако сообщество разрабатывает форк библиотеки, который поддерживает создание записей.

Файл Gradle требует:

 testImplementation 'io.github.dvgaba:easy-random-core:6.1.5'

С записью автомобиля:

public record Car(String brand, String model) {
}

Этот тест работает:

@Test
void shouldGenerateCarsRecords() {
     List<Car> cars = new EasyRandom().objects(Car.class, 5).toList();

     assertThat(cars.size()).isEqualTo(5);
     assertThat(cars)
             .allMatch(car -> !car.brand().isEmpty())
             .allMatch(car -> !car.model().isEmpty());
     cars.forEach(System.out::println);
}

Теперь, когда вы увидели несколько практических примеров того, как функциональность EasyRandom может упростить тестирование, теперь вы можете внедрить ее в свой код для нужд тестирования. Эта полезная функция Kotlin может помочь вам сэкономить часть вашего драгоценного времени и других ресурсов.

Узнать больше о Котлине

Полезные ссылки

Почетные упоминания: