zoukankan      html  css  js  c++  java
  • 开源神器:自动生成随机 mock 数据测试对象

    测试的痛点

    大家好,我是老马。

    每一位开发者大部分工作都是写代码、测试代码、修BUG。

    测试BUG.jpg

    我们有很多测试代码,总是花费大量的实践去构建一个对象。

    于是就在想,能不能自动填充一个对象呢?

    于是去 github 查了一下,找到了一个测试神器 data-factory。

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

    data-factory

    作用

    data-factory 项目用于根据对象,随机自动生成初始化信息。便于测试。

    特性

    • 8 大基本类型的支持

    • 数组、对象、枚举、Map、链表、Set 等支持

    • String、BigDecimal、BigInteger、Currency 等常见类型的支持

    • Date、LocalDate、LocalDateTime、LocalTime、Year 等常见日期类型支持

    • 支持 Regex 正则表达式

    • @DataFactory 注解支持灵活配置

    快速入门

    引入依赖

    <dependency>
        <groupId>com.github.houbb</groupId>
        <artifactId>data-factory-core</artifactId>
        <version>0.0.8</version>
    </dependency>
    

    我们通过 DataUtil.build(class) 就可以生成对应类的随机值。

    比如 DataUtil.build(String.class);,就可以生成随机的字符串:

    0s5Z8foS1
    

    老马发现,基本支持所有常见的类型,我们指定对应的 class 即可,这点还是挺方便的。

    不过我一般都是使用对象,那可以自动填充一个对象吗?

    自动化.jpg

    对象 bean 填充

    当然,最常用的还是初始化一个 java 对象。

    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
    }
    

    构建方法 User user = DataUtil.build(User.class);

    构建对象如下:

    User{name='wZ8CJZtK', age=-564106861, birthday=Wed Feb 27 22:14:34 CST 2019, stringList=[Du4iJkQj], statusEnum=S, map={yA5yDqM=Kdzi}}
    

    内容每次都随机,便于基本的测试数据填充。

    @DataFactory 注解

    当然,有时候我们希望生成的数据符合一定的规则,这个时候可以通过 @DataFactory 注解去进行限制。

    注解属性

    /**
     * 数据生成注解
     * @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 类

    • 定义对象
    /**
     * 字符串类注解测试
     * @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
    
    }
    
    • 测试代码
    /**
    *
    * 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 类

    • 对象定义
    /**
     * 数字类注解测试
     * @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
    
    }
    
    • 测试代码

    通过 DataUtil.build(UserAnnotationNumber.class) 生成的对象如下:

    UserAnnotationNumber{aByte=10, aShort=17, integer=19, aLong=11, aDouble=19.888, aFloat=10.067, bigDecimal=18.035, bigInteger=13}
    

    正则表达式

    正则表达式作为一大神器,自然是不能落下。

    定义

    对象的定义如下:

    /**
     * 正则表达式测试对象
     * @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
        
    }
    

    效果

    生成效果如下:

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

    自定义 Data 生成策略

    当然,所有的内置策略只能满足最常见的需求。

    但是无法满足各种特殊的定制化策略,幸运的是我们可以自定义自己的数据填充策略。

    自定义生成策略

    这里我们实现一个最简单的生成策略,如果是字符串,固定为 123。

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

    使用

    我们在 @DataFactory 注解中指定自己的策略。

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

    这样生成的就是我们自己的数据生成策略。

    不足之处

    当然,老马觉得这些特性还是不太方便。

    希望作者可以实现支持全局配置之类的特性,这样会更加方便的。

    各位小伙伴也可以体验一下,让自己早点下班,享受属于自己的时光。

    下班.jpg

    小结

    今天我们和大家一起感受了数据填充工具的便利性,大家工作中有需要就可以用起来。

    为了便于大家学习,所有源码均已开源:

    对象填充:https://github.com/houbb/data-factory

    性能压测:https://github.com/houbb/junitperf

    希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。

    我是老马,期待与你的下次相遇。

  • 相关阅读:
    使用jquery-qrcode生成二维码
    ASP.NET匿名对象与集合的使用
    ASP.NET Core 之跨平台的实时性能监控
    centos7如何将docker容器配置成开机自启动
    linux 查看系统信息命令
    基于.NET CORE微服务框架 -浅析如何使用surging
    Docker 两键创建 ZeroTier moon 节点
    kubernetes-dashboard获取令牌登陆
    docker环境下使用gitlab,gitlab-runner 为 NetCore 持续集成
    Docker For MYSQL 8.0 特别注意修复数据库新的验证方式
  • 原文地址:https://www.cnblogs.com/houbbBlogs/p/15017435.html
Copyright © 2011-2022 走看看