Pain points of testing
Hello everyone, I'm an old horse.
Most of the work of every developer is to write code, test code, and fix bugs.
We have a lot of test code and always spend a lot of practice to build an object.
So I was thinking, can an object be filled in automatically?
So I went to github to check and found a test artifact data-factory.
https://github.com/houbb/data-factory/
data-factory
effect
data-factory The project is used to randomly automatically generate initialization information according to the object. Easy to test.
characteristic
- 8 basic types of support
- Array, object, enumeration, Map, linked list, Set, etc. support
- String, BigDecimal, BigInteger, Currency and other common types support
- Date, LocalDate, LocalDateTime, LocalTime, Year and other common date types support
- Support Regex regular expression
@DataFactory
annotation supports flexible configuration
Quick start
Introduce dependencies
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>data-factory-core</artifactId>
<version>0.0.8</version>
</dependency>
We can generate the random value of the corresponding class DataUtil.build(class)
For example, DataUtil.build(String.class);
, you can generate a random string:
0s5Z8foS1
Lao Ma found that basically all common types are supported, and we can specify the corresponding class, which is quite convenient.
But I usually use objects. Can an object be automatically filled?
Object bean filling
Of course, the most commonly used is to initialize a java object.
public class User {
private String name;
private int age;
private Date birthday;
private List<String> stringList;
//S/F 的枚举
private StatusEnum statusEnum;
private Map<String, String> map;
//Getter & Setter
}
Construction method User user = DataUtil.build(User.class);
The construction objects are as follows:
User{name='wZ8CJZtK', age=-564106861, birthday=Wed Feb 27 22:14:34 CST 2019, stringList=[Du4iJkQj], statusEnum=S, map={yA5yDqM=Kdzi}}
The content is random every time, which is convenient for basic test data filling.
@DataFactory
comment
Of course, sometimes we want the generated data to comply with certain rules. At this time, we can use the @DataFactory
annotation to restrict it.
Annotation attributes
/**
* 数据生成注解
* @author binbin.hou
* @date 2019/3/9
* @since 0.0.2
*/
@Inherited
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataFactory {
/**
* 是否忽略此字段
*
* @return 默认不忽略
*/
boolean ignore() default false;
/**
* 数字整数部分最大值。
* 只作用于数字类型的字段
*
* @return 返回最大值
*/
int max() default 100;
/**
* 数字整数部分最小值。
* 只作用于数字类型的字段
*
* @return 返回最小值
*/
int min() default 0;
/**
* 精度。
* 作用于Float、Double、BigDecimal 小数部分长度
*
* @return 返回精度
*/
int precision() default 2;
/**
* 最大长度。只作用于String类型的字段
*
* @return 返回最大长度
*/
int maxLen() default 30;
/**
* 最小长度。只作用于String类型的字段
*
* @return 返回最小长度
*/
int minLen() default 1;
/**
* 指定当前字段的类实现策略
* @return 实现类
* @since 0.0.6
*/
Class<? extends IData> data() default IData.class;
/**
* 正则表达式
* 1. 当前版本为了简单方便,如果 regex 存在,则直接忽略长度,精度等其他注解配置。
* 2. 建议直接使用在 String 类型
* 3. 如果使用其他类型,则必须保证提供了对应的 String 构造器。如{@link Long#Long(String)}
* 4. 基本类型会直接使用对应的包装类型。
* @since 0.0.3
* @return 表达式信息
*/
String regex() default "";
}
String class
- Define the object
/**
* 字符串类注解测试
* @author binbin.hou
* @date 2019/3/9
* @since 0.0.2
*/
public class UserAnnotationString {
/**
* 指定最小长度,最大长度
*/
@DataFactory(minLen = 2, maxLen = 10)
private String name;
/**
* 忽略生成当前字段
*/
@DataFactory(ignore = true)
private String hobby;
//Getter & Setter
}
- Test code
/**
*
* Method: build(clazz)
*/
@Test
public void stringAnnotationTest() 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);
}
}
Number class
- Object definition
/**
* 数字类注解测试
* @author binbin.hou
* @date 2019/3/9
* @since 0.0.2
*/
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
}
- Test code
The objects generated by DataUtil.build(UserAnnotationNumber.class)
are as follows:
UserAnnotationNumber{aByte=10, aShort=17, integer=19, aLong=11, aDouble=19.888, aFloat=10.067, bigDecimal=18.035, bigInteger=13}
Regular expression
As a great artifact, regular expressions naturally cannot be left behind.
definition
The definition of the object is as follows:
/**
* 正则表达式测试对象
* @author binbin.hou
* @date 2019/3/12
* @since 0.0.3
*/
public class RegexBean {
@DataFactory(regex = "[0-3]([a-c]|[e-g]{1,2})")
private String name;
@DataFactory(regex = "[0-9]{1,2}")
private int age;
@DataFactory(regex = "[0-9]{1,2}")
private BigDecimal amount;
//Getter & Setter
}
effect
The effect is as follows:
RegexBean{name='2c', age=61, amount=39}
Custom data generation strategy
Of course, all built-in strategies can only meet the most common needs.
But it cannot meet various special customized strategies. Fortunately, we can customize our own data filling strategy.
Custom build strategy
Here we implement one of the simplest generation strategy, if it is a string, it is fixed at 123.
public class MyStringData implements IData<String> {
@Override
public String build(IContext context, Class<String> stringClass) {
return "123";
}
}
use
We specify our own strategy in the @DataFactory
public class UserAnnotationData {
@DataFactory(data = MyStringData.class)
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
What is generated in this way is our own data generation strategy.
Shortcomings
Of course, Lao Ma thinks these features are still not convenient.
I hope that the author can implement features such as support for global configuration, which will be more convenient.
Everyone can also experience it, let yourself get off work early and enjoy your own time.
summary
Today we felt the convenience of the data filling tool with you, and you can use it if you need it in your work.
In order to facilitate everyone to learn, all the source code has been open source:
Object filling: https://github.com/houbb/data-factory
Performance pressure test: https://github.com/houbb/junitperf
I hope this article is helpful to you. If you like it, please like, collect and forward a wave.
I am an old horse, and I look forward to meeting you next time.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。