自动化测试常用的数据驱动方式

来源:互联网 发布:网络教学综合平台 编辑:程序博客网 时间:2024/06/08 08:09
在日常的测试工作中,从理论上来说,一个接口方法可以用一个用例就搞定测试,然后传入不同的参数的不同组合,在用例方法里做不同的分支判断校验。看似很美好,包罗万象的参数组合,实现其来很麻烦,且有如下缺点:
  1. 且需要花大量的精力去判断分支路径,并做不同的断言,破坏了方法的原子性,不要指望一个方法干所有事情,我们一直强调模块化编程。
  2. 脚本存在大量的if-else分支,for循环等,脚本可读性差 维护成本高。
  3. 测试没有侧重点。
那么,有什么好的方法来避免这个问题呢?首先,我们要明白为什么要做数据驱动,数据驱动的原则是什么?这个问题,相同字段,输入不同的数据,通过调取被测代码,获取不同的测试结果。每组数据都是相同的字段,进一步可以把一组参数抽象为一个对象,这一组参数组合就是这个对象的不同元素。我们要做的工作就是不断创建这样的对象,并传递给测试方法。那么数据驱动怎么做呢?有哪些数据驱动方式呢?一般来说,主要有以下几种方式传入数据:
  1. 以硬编码的方式写在代码里,简单直观,但代码和数据未分离,不方便以后维护。
  2. 从文件读取数据,如csv,excel、txt、xml等格式文件。不用修改测试逻辑,只需要维护测试数据。
  3. 直接调用接口获取数据源。
  4. 本地封装一些生成数据的方法。
以上几种方式生成的数据,在@DataProvider方法中以Object二位数组返回数据,测试用例可以直接获取。通过@datapovider方法数据驱动有以下几点优点:
1.像在循环里一样,自动遍历所有数据组合
2.某一组数据执行测试方法失败,不会影响其他数据组合继续执行。
3.测试代码不用加过多的数据判断,要的只是对被测代码的数据输出和结果断言。
例如要测试一个列表查询的接口,有很多查询条件,那么需要测试,默认查询、单一条件查询、组合条件查询等场景,其实就是设置不同的查询参数,其余测试步骤及校验大抵相同。
1.单一条件查询,遍历所有查询条件,传入测试方法,数据的获取需要封装成合适的方法,可读性好,例如这里buildQueryParmGroup方法就是封装构造查询参数的方法
private static Map<String, String> buildQueryParmGroup() {    HashMap<String, String> map = new HashMap<String, String>();    map.put("id", "1003266");    map.put("type", "1");    map.put("venderId", "20032");    map.put("businessId", "100073920");    map.put("title", "砍价活动api测试");    map.put("skuId", "1200039810");    map.put("oneCategory", "1315");    map.put("twoCategory", "1342");    map.put("threeCategory", "9733");    map.put("beginTime", "2017-01-04 16:19:45");    map.put("endTime", "2017-02-03 16:19:45");    map.put("status", "1");    map.put("pin", "test_sop01");    map.put("customerPin", "sop_order_new");    return map;}

  @DataProvider(name = "queryParamProperties")    public static Object[][] queryParamProperties() {        Map<String, String> queryParmGroup = buildQueryParmGroup();        Set<Map.Entry<String, String>> entrySet = queryParmGroup.entrySet();        Object[][] objects = new Object[entrySet.size()][];        Object[] objects1 = entrySet.toArray();        for (int i = 0; i < objects.length; i++) {            objects[i] = new Object[]{objects1[i]};        }        return objects;    }    @Test(dataProvider = "queryParamProperties")    @Description(description = "单一条件查询砍价列表")    public void testGetByBargainList_2(Map.Entry<String, String> entry) throws Exception {//        ConvertUtils.register(new DateLocaleConverter(), Date.class);        ConvertUtils.register(new Converter() {            public Object convert(Class type, Object value) {                if (value == null) {                    return null;                }                if (!(value instanceof String)) {                    throw new ConversionException("传入的不是字符串");                }                if (((String) value).trim().equals("")) {                    return null;                }                DateFormat df = new SimpleDateFormat(PromoConstant.YYYYMMDDHHMMSS);                try {                    return df.parse((String) value);                } catch (ParseException e) {                    throw new RuntimeException(e);                }            }        }, Date.class);        BargainQueryParm queryParam = new BargainQueryParm();        BeanUtils.setProperty(queryParam, entry.getKey(), entry.getValue());        Result<List> bargainList = this.invoke(bargainReadService, "getBargainList", List.class, clientInfo, queryParam);        Assert.assertTrue(bargainList.isSuccess());    }
组合条件查询,随机生成参数组合,查询条件放到一个map里,封装一个buildQueryParmSubMap方法用于随机生成查询条件组合,返回一个map<条件参数名,条件参数值>
private static Map<String, String> buildQueryParmSubMap(Map<String, String> map, int size) {    Set<Map.Entry<String, String>> entries = map.entrySet();    ImmutableSet<Map.Entry<String, String>> subSet = ImmutableSet.copyOf(Iterables.limit(entries, size));    Map<String, String> subMap = new HashMap<String, String>();    Iterator<Map.Entry<String, String>> iterator = subSet.iterator();    while (iterator.hasNext()) {        Map.Entry<String, String> entry = iterator.next();        subMap.put(entry.getKey(), entry.getValue());    }    return subMap;}
数据驱动方法:
@DataProvider(name = "queryParmGroup")public static Object[][] queryParmGroup() {    Map<String, String> queryParmGroup = buildQueryParmGroup();    Object[][] objects = new Object[100][];    for (int i = 0; i < objects.length; i++) {        objects[i] = new Object[]{buildQueryParmSubMap(queryParmGroup, RandomUtils.nextInt(queryParmGroup.size()))};    }    return objects;}
@Test(dataProvider = "queryParmGroup")@Description(description = "组合条件查询砍价列表")public void testGetByBargainList_3(Map<String, String> map) throws Exception {    ConvertUtils.register(new Converter() {        public Object convert(Class type, Object value) {            if (value == null) {                return null;            }            if (!(value instanceof String)) {                throw new ConversionException("传入的不是字符串");            }            if (((String) value).trim().equals("")) {                return null;            }            DateFormat df = new SimpleDateFormat(PromoConstant.YYYYMMDDHHMMSS);            try {                return df.parse((String) value);            } catch (ParseException e) {                throw new RuntimeException(e);            }        }    }, Date.class);    BargainQueryParm queryParam = new BargainQueryParm();    BeanUtils.populate(queryParam, map);    Result<List> getBargainList = this.invoke(bargainReadService, "getBargainList", List.class, clientInfo, queryParam);    Assert.assertTrue(getBargainList.isSuccess());}


0 0
原创粉丝点击