Статьи

Генерация тестовых данных с DataFactory

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

Чтобы добавить DataFactory в свой проект maven, просто добавьте его в качестве зависимости в файле pom.xml.

<dependency>
<groupId>org.fluttercode.datafactory</groupId>
<artifactId>datafactory</artifactId>
<version>0.8</version>
<type>jar</type>
</dependency>

Генерация тестовых данных

Теперь вы можете создавать экземпляры класса DataFactory и создавать данные:

public class Main {

public static void main(String[] args) {
DataFactory df = new DataFactory();
for (int i = 0; i < 100; i++) {
String name = df.getFirstName() + " "+ df.getLastName();
System.out.println(name);
}
}
}

Полученная продукция:

Lindsey Craft
Erica Larsen
Ryan Levine
Erika Smith
Brooklyn Sloan
Karen Mayer
Eddie O'neill
Nancy Stevens

Класс DataFactory может генерировать различные типы значений, от адресов до случайного текста и случайных дат, до дат в пределах фиксированного периода времени.
Адреса и названия компаний можно создать с помощью следующего кода:
DataFactory df = new DataFactory();
for (int i = 0; i < 100; i++) {
String address = df.getAddress()+","+df.getCity()+","+df.getNumberText(5);
String business = df.getBusinessName();
System.out.println(business + " located at " + address);
}
производить
Uvalda Signs located at 1383 Beam Way,Lyons,19316
Alma Accounting located at 1386 Countiss St,Nashville,14967
Fort Stewart Engineering located at 1753 Bethesda Rd,Springfield,26306
Sugar Hill Textiles located at 1141 Loudon Circle,Cordele,83937
Albany Engineering located at 1185 Grieves Avenue,Sugar Hill,36753
Poulan Insurance located at 816 Cohen Blvd,Lake City,74839
Crescent Services located at 1085 Cloveridge Boulevard,Bemiss,08769

Даты

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

DataFactory df = new DataFactory();
Date minDate = df.getDate(2000, 1, 1);
Date maxDate = new Date();
for (int i = 0; i < 10; i++) {
Date start = df.getDateBetween(minDate, maxDate);
System.out.println("Date = "+start);
}

Это создает список случайных дат между 01.01.2000 и текущей датой. Как правило, случайная дата может быть ограничена какой-либо другой датой, например, у вас не может быть конечной даты, которая наступает до начальной даты. В этом случае вы бы включили дату начала в качестве минимального значения даты:

DataFactory df = new DataFactory();
Date minDate = df.getDate(2000, 1, 1);
Date maxDate = new Date();

for (int i = 0; i < 10; i++) {
Date start = df.getDateBetween(minDate, maxDate);
Date end = df.getDateBetween(start, maxDate);
System.out.println("Date range = " + dateToString(start) + " to " + dateToString(end));
}

Результатом является список дат, где вторая дата всегда позже первой:

Date range = 04/29/2005 to 07/16/2006
Date range = 08/07/2009 to 01/19/2010
Date range = 09/22/2000 to 12/15/2003
Date range = 07/31/2004 to 03/24/2009
Date range = 06/27/2003 to 01/10/2007
Date range = 07/10/2003 to 04/02/2008
Date range = 01/04/2003 to 01/12/2005

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

for (int i = 0; i < 10; i++) {
Date start = df.getDateBetween(minDate, maxDate);
Date end = df.getDate(start, 0, 10); //set end to within 10 days of the start
System.out.println("Date range = " + dateToString(start) + " to " + dateToString(end));
}

И результат:

Date range = 04/29/2005 to 04/30/2005
Date range = 12/29/2003 to 12/30/2003
Date range = 06/25/2003 to 07/03/2003
Date range = 10/19/2009 to 10/19/2009

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

for (int i = 0; i < 10; i++) {
//generate an order date
Date orderDate = df.getDateBetween(minDate, maxDate);

//estimate delivery 4-10 days after ordering
Date estimatedDeliveryDate = df.getDate(orderDate, 4, 10);

//deliver between 2 days prior and 3 days after delivery estimate
Date actualDeliveryDate = df.getDate(estimatedDeliveryDate, -2, 3);

String msg = "Ordered on "+dateToString(orderDate) +
" deliver by = "+dateToString(estimatedDeliveryDate)+
" delivered on " + dateToString(actualDeliveryDate);

if (estimatedDeliveryDate.before(actualDeliveryDate)) {
msg = msg + " - LATE";
}
if (estimatedDeliveryDate.after(actualDeliveryDate)) {
msg = msg + " - EARLY";
}
System.out.println(msg);
}

Здесь мы рассчитываем дату заказа и создаем дату доставки, которая составляет не менее 4 дней, но не более 10, а затем мы создали фактическую дату доставки, которая составляет от 2 дней до 3 дней после ожидаемой даты доставки.
Обратите внимание, как мы выбрали даты, предполагаемая дата доставки не менее 4 дней с даты заказа, а фактическая дата доставки будет не более 2 дней до предполагаемой даты. Это означает, что фактическая дата доставки всегда составляет не менее 2 дней с даты заказа, и мы не получим значение даты доставки, которое было до заказа товара. Этот код производит следующие значения:

Ordered on 04/29/2005 deliver by = 05/06/2005 delivered on 05/06/2005
Ordered on 08/07/2009 deliver by = 08/13/2009 delivered on 08/13/2009
Ordered on 09/22/2000 deliver by = 09/27/2000 delivered on 09/25/2000 - EARLY
Ordered on 07/31/2004 deliver by = 08/07/2004 delivered on 08/09/2004 - LATE
Ordered on 06/27/2003 deliver by = 07/04/2003 delivered on 07/04/2003
Ordered on 07/10/2003 deliver by = 07/19/2003 delivered on 07/18/2003 - EARLY
Ordered on 01/04/2003 deliver by = 01/08/2003 delivered on 01/08/2003

Пользовательские случайные значения

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

public static void main(String[] args) {
DataFactory df = new DataFactory();

//favorite animal
String[] values = {"Cat","Dog","Goat","Horse","Sheep"};
for (int i = 0; i < 100; i++) {
System.out.println(df.getItem(values,80,"None"));
}
}

В этом примере используется массив животных и возвращается значение с вероятностью 20%, являющееся значением по умолчанию «Нет», для получения следующего:

Sheep
None
Dog
Horse

Текстовые данные

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

DataFactory df = new DataFactory();
System.out.println(df.getRandomText(20, 25));
System.out.println(df.getRandomChars(20));
System.out.println(df.getRandomWord(4, 10))

который производит

badly numbers good hot I
ywyypgqorighfawpftjq
demanded

Всем трем из этих методов может быть передана единственная длина, которая возвращает строку фиксированной длины, или длина min / max, которая создает случайную строку с длиной где-то между min / max. Для метода с одним словом, если в словаре нет подходящей длины слов, то слово генерируется с использованием случайных символов.

Изменение значений тестовых данных

The data used to generate the values come from classes that can be replaced with other versions. For example, the name values can be changed by providing the DataFactory instance with an object that implements the NameDataValues interface. Here is a simple class that does that to return Scandinavian first names and delegates to the the default implementation to return all the other values.

public class ScandinavianNames  implements NameDataValues {

//first name values to use
String[] firstNames = {"Anders","Freydís","Gerlach","Sigdis"};

//delegate to the default implementation for the other values
NameDataValues defaults = new DefaultNameDataValues();

public String[] getFirstNames() {
//return our custom list of names
return firstNames;
}

//for the other values, just use the defaults
public String[] getLastNames() {
return defaults.getLastNames();
}

public String[] getPrefixes() {
return defaults.getPrefixes();
}

public String[] getSuffixes() {
return defaults.getSuffixes();
}

}
Obviously, to use all your own names you would add and return values for last name and the suffix/prefix values. To use this new implementation, just create an instance of the data provider and pass it to the instance of the data factory.
public static void main(String[] args) {
DataFactory df = new DataFactory();
df.setNameDataValues(new ScandinavianNames());
for (int i = 0; i < 10; i++) {
System.out.println(df.getName());
}
}
Our results are
Sigdis Craft
Gerlach Larsen
Sigdis Levine
Sigdis Smith
Freydís Sloan
Gerlach Mayer

You can always start working with the default implementation and use a more locale specific implementation if you need it later.

The different pieces that can be replaced are as follows :

  • NameDataValues – Generates names and suffix/prefixes
  • ContentDataValues.java – Generates words, business types, email domain names and top level domain values
  • AddressDataValues – Generates city names, street names and address suffixes

Note that if you intend on replacing the component that generates words, you should have a good collection of words of various lengths from 2 up to say 8 or more characters.

Hopefully this will give you a head start in generating data in development and test environments for new projects. Now I have DataFactory in the Central Maven Repository I plan on using this in the Knappsack archetypes rather than hard coding the data which was in fact generated from an earlier DataFactory implementation.

From http://www.andygibson.net/blog/article/generate-test-data-with-datafactory/