一步一步学做测试工具(Spring Boot版)之三
- 2020 年 1 月 20 日
- 筆記
通过前面两节的介绍,相信小伙伴们已经掌握了如何在SpringBoot的进行Http的请求操作,也可以顺利的使用代码来进行接口的测试。如果没有掌握,可以翻看之前关于SpringBoot的文章。好了,废话不多说,咱们还是直接上干货,本节就介绍冒烟测试工具的核心思想MC/DC。
什么是 MC/DC
MC/DC(Modified Condition/Decision Coverage)是一种软件结构覆盖率测试准则, 通过最少N+1(N为Condition个数)个case就能对软件的进行较好的测试。
Condition 和 Decision 的概念
if(A or B and C) then Statement; else Statement2;
A
,B
,C
都是一个Condition
(A or B and C)
是一个Decision
有效case数,最少N+1个
在每个判定中的每个条件都曾独立的影响判定的结果至少一次(独立影响意思是在其他的条件不变的情况下只改变一个条件),简单来说就是每个条件对结果都独立起一次作用。
这样得出来的最小case数就是N+1。
Condition |
Case 序号 |
A |
B |
C |
结果 |
---|---|---|---|---|---|
A |
1 |
true |
false |
true |
true |
A |
2 |
false |
false |
true |
false |
B |
3 |
false |
true |
true |
true |
B |
4 |
false |
false |
true |
false |
C |
5 |
false |
true |
true |
true |
C |
6 |
false |
true |
false |
false |
比如A
对结果起作用的话,B
必须为false
,C
必须为true
—- 也就是 Case1(true/false/true)
和 Case2 (false/false/true)
, 这样结果就独立受A
的值影响。
同理如果B
对结果独立起作用的话,A
必须为false
, C
必须为true
, 两种情况B
为true
,false
各一次,即Case3 (false/true/true)
和 Case4(false/false/true)
而C
独立对结果起作用的话就是让(A or B)
为 true
, 我们就取A
为false
,B
为true
, 这样c
独体起作用的case为 Case5(false/true/true)
和 Case6(false/true/false)
可以看出每个条件各走了一次true
和false
, 这样三个变量条件就会有六个case, 我们看出其中里面还有两个是重复的Case2/Case4,Case3/Case5
除去重复的Case4、Case5,那么最后的有效Case数是4,等于3+1个。
代码实现MC/DC
/** * 函数说明:1.入参为 MultiValueMap类型,主要考虑使用 RestTemplate进行http请求更为方便 * sourceMap 为被测接口的正确的请求体 * * 2.返回值为List类型,List中的元素为MultiValueMap类型 * 因为根据MC/DC覆盖会生成多条被测接口的异常请求体 * * @param sourceMap * @return * List<Map<String,String>> * */ publicList<MultiValueMap<String, String>> getMCDCparams (MultiValueMap<String, String> sourceMap) { // MCDCList 为拼接后的list List<MultiValueMap<String, String>> MCDCList= newArrayList<>(); // 首先将正常的请求body放入MCDCList MCDCList.add(sourceMap); /* 嵌套循环: * 第一层循环(根据key遍历sourceMap,生成对应key的异常value): * 获取当前key值,命名为 sourceKey * 声明异常value,命名为 nullValue * 声明 MultiValueMap类型的变量用来拼接异常请求体,命名为 destMapNull * * 第二层循环(再次根据key遍历sourceMap,并将key-value重新组装成map): * 获取当前key值,命名为 destKey * 比对destKey与sourceKey * 如果destKey == sourceKey * 将destKey对应的value置为异常值nullValue,并将 destKey->nullValue 放入destMapNull * 其余的 * destKey 对应的 value 为原来正确的 value,也将 destKey->value 放入destMapNull * * 第二层循环结束会获得destMapNull,并且拥有与sourceMap一样的key,但是其中有且只有一个key对应的value是异常的nullValue * 将destMapNull放入MCDCList * * 第一层循环结束后,会获得一个完整的符合MCDC规则的请求体列表 MCDCList * */ for(Iterator<String> iterator = sourceMap.keySet().iterator(); iterator.hasNext();) { String sourceKey = iterator.next(); String nullValue = ""; MultiValueMap<String, String> nullDestMap= newLinkedMultiValueMap<>(); for(Iterator<String> iterator1 = sourceMap.keySet().iterator(); iterator1.hasNext();) { String destKey = iterator1.next(); if(destKey.equals(sourceKey)) { nullDestMap.add(destKey, nullValue); } else{ nullDestMap.add(destKey, sourceMap.getFirst(destKey)); } } MCDCList.add(nullDestMap); } returnMCDCList; }
测试不可少
简单的测试一下MC/DC有没有生效:
依旧使用电话区号查询的API,入参有两个,那么执行的请求应该是2+1
3条

至此一个简单的API自动冒烟测试就实现了,是不是非常简单。
当然还有更多的用例组合,比如,可以把区号看成一个Decision,长度增加一位、减少一位等等也是MC/DC的思想。
留给小伙伴们来练手实现!