Testing pain points

Hello, I’m Lao Ma.

The majority of every developer’s job is to write code, test code, and fix bugs.

We have a lot of test code and it always takes a lot of practice to build an object.

So I was wondering, can I auto-populate an object?

So I went to GitHub and found a test artifact called Data-Factory.

https://github.com/houbb/data-factory/

data-factory

role

The Data-Factory project is used to randomly and automatically generate initialization information based on the object. Easy to test.

features

  • 8 basic types of support
  • Arrays, objects, enumerations, maps, linked lists, sets and other support
  • Support for common types such as String, BigDecimal, BigInteger, Currency, etc
  • Common Date types such as DATE, LOCALDATE, LOCALDATETIME, LOCALTIME, YEAR are supported
  • Support for Regex regular expressions
  • @DataFactoryAnnotations support flexible configuration

Quick start

Introduction of depend on

< the dependency > < groupId > com. Making. Houbb < / groupId > < artifactId > data - factory - core < / artifactId > < version > 0.0.8 < / version > </dependency>

Build (class) generates a random value for the corresponding class.

Such as DataUtil. Build (String. Class); To generate a random string:

0s5Z8foS1

I found it convenient to support almost all the common types and just specify the corresponding class.

But I usually use objects, so can I automatically populate an object?

Object bean population

Of course, the most common is to initialize a Java object.

public class User { private String name; private int age; private Date birthday; private List<String> stringList; Private StatusEnum private StatusEnum private StatusEnum; private Map<String, String> map; //Getter & Setter }

Build method User User = datautil.build (user.class);

The construction object is 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 each time to facilitate basic test data filling.

@DataFactoryannotations

Of course, there are times when you want the generated data to conform to certain rules, which can be restricted by the @DataFactory annotation.

Annotation properties

* @Author Binbin.Hou * @Date 2019/3/9 * @Since 0.0.2 */ @Inherited @Documented @Target(ElementTyp.field) Public @ @ Retention (RetentionPolicy RUNTIME) interface DataFactory {/ * * * * * @ return whether to ignore this field default don't ignore the * / Boolean ignore () default false; /** * Number integer part maximum. * * @return returns the maximum value */ int Max () default 100; /** * Minimal integer part of the number. * * @return returns the minimum value */ int min() default 0; /** * Accuracy. * * @return return precision */ int precision() default 2; /** * Maximum length. * * @return returns maximum length */ int maxLen() default 30; /** * Minimum length. Int minLen() default 1; int minLen() default 1; /** * specify the Class implementation policy for the current field * @return implementation Class * @since 0.0.6 */ Class<? extends IData> data() default IData.class; /** * regular expression * 1. In the current version, if the regex is present, the length, precision and other annotation configurations are ignored. 3. If you use any other type, you must ensure that the corresponding String constructor is provided. {@link Long#Long(String)} * 4. The primitive type uses the corresponding wrapper type directly. * @since 0.0.3 * @return expression information */ String regex() default ""; }

The String class

  • Define the object
/** * public class UserAnnotationString {/** * AnnotationString * @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 }
  • The 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 definitions
/** * @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 }
  • 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, convertible =10.067, BigDecimal =18.035, bigInteger=13}

Regular expression

As a great artifact, regular expressions can’t be left behind.

define

The object is defined as follows:

/** * public class RegexBean {@dataFactory (regex = dataFactory) "[0, 3], [c] a - | - g [e] {1, 2})") private String name; @dataFactory (regex = "[0-9]{1,2}") private int age; @dataFactory (regex = "[0-9]{1,2}") private BigDecimal Aamount; //Getter & Setter }

The effect

The effect is as follows:

RegexBean{name='2c', age=61, amount=39}

Customize Data generation policies

Of course, all the built-in policies can only meet the most common requirements.

However, there is no way to satisfy a variety of special customization policies. Fortunately, we can customize our own data population policies.

Customize the build policy

Here we implement the simplest generation strategy, which is fixed as 123 if it is a string.

public class MyStringData implements IData<String> { @Override public String build(IContext context, Class<String> stringClass) { return "123"; }}

use

We specify our own policy in the @DataFactory annotation.

public class UserAnnotationData { @DataFactory(data = MyStringData.class) private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }}

The result is our own data generation strategy.

Deficiency in

Of course, Ma finds these features inconvenient.

Hopefully, the author can implement features like support for global configuration, which will be more convenient.

You can also experience it, let yourself leave work early, enjoy their own time.

summary

Today, we feel the convenience of data filling tool with you, you can use it if you need it in your work.

For your convenience, all the source code has been open source:

Object: https://github.com/houbb/data-factory

Performance pressure test: https://github.com/houbb/junitperf

I hope you found this article helpful. If you like it, please feel free to share it with your thumb up favorites.

I am Lao Ma, looking forward to the next meeting with you.