測試的痛點
大家好,我是老馬。
每一位開發者大部分工作都是寫程式碼、測試程式碼、修BUG。
我們有很多測試程式碼,總是花費大量的實踐去構建一個物件。
於是就在想,能不能自動填充一個物件呢?
於是去 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 即可,這點還是挺方便的。
不過我一般都是使用物件,那可以自動填充一個物件嗎?
物件 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)*/@Testpublic 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; }}
這樣生成的就是我們自己的資料生成策略。
不足之處當然,老馬覺得這些特性還是不太方便。
希望作者可以實現支援全域性配置之類的特性,這樣會更加方便的。
各位小夥伴也可以體驗一下,讓自己早點下班,享受屬於自己的時光。
小結今天我們和大家一起感受了資料填充工具的便利性,大家工作中有需要就可以用起來。
為了便於大家學習,所有原始碼均已開源:
物件填充:https://github.com/houbb/data-factory
效能壓測:https://github.com/houbb/junitperf
我是老馬,期待與你的下次相遇。