Pain points of testing
Hello, I’m Ma.
Most of every developer’s job is to write code, test code, and fix bugs.
We have a lot of test code, and it takes a lot of practice to build an object.
So I was thinking, can I fill an object automatically?
So I went to Github and found a test artifact called data-Factory.
Github.com/houbb/data-…
data-factory
role
The data-factory project is used to randomly and automatically generate initialization information based on objects. Easy to test.
features
-
Eight basic types are supported
-
Arrays, objects, enumerations, maps, linked lists, sets, and more are supported
-
Support for common types such as String, BigDecimal, BigInteger, Currency, etc
-
Date, LocalDate, LocalDateTime, LocalTime, and Year are supported
-
Support for Regex regular expressions
-
@datafactory Annotations support flexible configuration
Quick start
Introduction of depend on
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>data-factory-core</artifactId>
<version>0.0.8</version>
</dependency>
Copy the code
Datautil.build (class) generates a random value for the corresponding class.
Such as DataUtil. Build (String. Class); To generate a random string:
0s5Z8foS1
Copy the code
Ma found it convenient to specify a class for all common types.
But I usually work with objects, so can I automatically populate an object?
Object Bean population
The most common, of course, is to initialize a Java object.
public class User {
private String name;
private int age;
private Date birthday;
private List<String> stringList;
/ / S/F of the enumeration
private StatusEnum statusEnum;
private Map<String, String> map;
//Getter & Setter
}
Copy the code
User User = datautil.build (user.class);
Build objects as follows:
User{name='wZ8CJZtK', age=-564106861, birthday=Wed Feb 27 22:14:34 CST 2019, stringList=[Du4iJkQj], statusEnum=S, map={yA5yDqM=Kdzi}}
Copy the code
The content is random each time, making it easy to populate basic test data.
@DataFactory
annotations
Of course, there are times when we want the generated data to conform to certain rules, and this can be restricted by the @Datafactory annotation.
Annotation properties
/** * Data generation annotation *@author binbin.hou
* @date 2019/3/9
* @sinceHundreds * /
@Inherited
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataFactory {
/** * Whether to ignore this field **@return*/ is not ignored by default
boolean ignore(a) default false;
/** * Number Specifies the maximum number of integers. * Only fields of numeric type * *@returnReturns the maximum value */
int max(a) default 100;
/** * The smallest part of a numeric integer. * Only fields of numeric type * *@returnReturns the minimum value */
int min(a) default 0;
/** * precision. * Works on Float, Double, BigDecimal fraction length * *@returnReturn precision */
int precision(a) default 2;
/** * Maximum length. Only fields of type String * *@returnReturns the maximum length */
int maxLen(a) default 30;
/** * Minimum length. Only fields of type String * *@returnReturns the minimum length */
int minLen(a) default 1;
/** * Specifies the class implementation policy * for the current field@returnThe implementation class *@since0.0.6 * /
Class<? extends IData> data() default IData.class;
/** * regular expressions * 1. For simplicity, the current version ignores length, precision, and other annotation configurations if regex exists. 3. If you use other types, you must ensure that the corresponding String constructor is provided. Such as {@linkLong#Long(String)} * 4. Base types will use the corresponding wrapper type directly. *@since 0.0.3
* @returnExpression information */
String regex(a) default "";
}
Copy the code
The String class
- Define the object
/** * string class annotation test *@author binbin.hou
* @date 2019/3/9
* @sinceHundreds * /
public class UserAnnotationString {
/** * specifies the minimum length and the maximum length */
@DataFactory(minLen = 2, maxLen = 10)
private String name;
/** * ignores generating the current field */
@DataFactory(ignore = true)
private String hobby;
//Getter & Setter
}
Copy the code
- The test code
/**
*
* Method: build(clazz)
*/
@Test
public void stringAnnotationTest(a) throws Exception {
for(int i = 0; i < 100; i++) {
UserAnnotationString userAnnotationString = DataUtil.build(UserAnnotationString.class);
Assertions.assertNull(userAnnotationString.getHobby());
Assertions.assertTrue(userAnnotationString.getName().length() >= 2);
Assertions.assertTrue(userAnnotationString.getName().length() <= 10); }}Copy the code
Number class
- Object definitions
/** * number class annotation test *@author binbin.hou
* @date 2019/3/9
* @sinceHundreds * /
public class UserAnnotationNumber {
@DataFactory(min = 10, max = 20)
private Byte aByte;
@DataFactory(min = 10, max = 20)
private Short aShort;
@DataFactory(min = 10, max = 20)
private Integer integer;
@DataFactory(min = 10, max = 20)
private Long aLong;
@DataFactory(min = 10, max = 20, precision = 3)
private Double aDouble;
@DataFactory(min = 10, max = 20, precision = 3)
private Float aFloat;
@DataFactory(min = 10, max = 20, precision = 3)
private BigDecimal bigDecimal;
@DataFactory(min = 10, max = 20)
private BigInteger bigInteger;
//Getter & Setter
}
Copy the code
- The test code
Through DataUtil. Build (UserAnnotationNumber. Class) generated object is as follows:
UserAnnotationNumber{aByte=10, aShort=17, INTEGER =19, aLong=11, aDouble=19.888, sticker =10.067, bigDecimal=18.035, bigInteger=13}Copy the code
Regular expression
Regular expressions are a great tool that can’t be left behind.
define
The object is defined as follows:
/** * Regular expression test object *@author binbin.hou
* @date 2019/3/12
* @since0.0.3 * /
public class RegexBean {
@ the DataFactory (regex = "[0, 3], [c] a - | - g [e]} {1, 2)")
private String name;
@ the DataFactory (regex = "[0-9] {1, 2}")
private int age;
@ the DataFactory (regex = "[0-9] {1, 2}")
private BigDecimal amount;
//Getter & Setter
}
Copy the code
The effect
The result is as follows:
RegexBean{name='2c', age=61, amount=39}
Copy the code
Customize the Data generation policy
Of course, all built-in policies only meet the most common requirements.
However, there are no specific customization strategies available, and fortunately we can customize our own data populating strategy.
Customize the generation policy
Here we implement the simplest generation strategy, which is set to 123 if it is a string.
public class MyStringData implements IData<String> {
@Override
public String build(IContext context, Class<String> stringClass) {
return "123"; }}Copy the code
use
We specify our policy in the @Datafactory annotation.
public class UserAnnotationData {
@DataFactory(data = MyStringData.class)
private String name;
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name; }}Copy the code
The result is our own data generation strategy.
Deficiency in
Of course, Ma found these features inconvenient.
Hopefully the authors can implement features such as support for global configuration, which would be more convenient.
Friends can also experience, let yourself leave work early, enjoy their own time.
summary
Today we experienced the convenience of data filling tools, which you can use when you need them in your work.
For your convenience, all source code is open source:
Object filling: github.com/houbb/data-…
Performance pressure measurement: github.com/houbb/junit…
I hope this article is helpful to you. If you like it, please click to collect and forward a wave.
I am an old horse, looking forward to meeting with you next time.