通过前面两节的介绍,相信小伙伴们已经掌握了如何在SpringBoot的进行Http的请求操作,也可以顺利的使用代码来进行接口的测试。如果没有掌握,可以翻看之前关于SpringBoot的文章。好了,废话不多说,咱们还是直接上干货,本节就介绍冒烟测试工具的核心思想MC/DC。
MC/DC(Modified Condition/Decision Coverage)是一种软件结构覆盖率测试准则, 通过最少N+1(N为Condition个数)个case就能对软件的进行较好的测试。
if(A or B and C) then
Statement;
else
Statement2;
A
,B
,C
都是一个Condition
(A or B and C)
是一个Decision
在每个判定中的每个条件都曾独立的影响判定的结果至少一次(独立影响意思是在其他的条件不变的情况下只改变一个条件),简单来说就是每个条件对结果都独立起一次作用。
这样得出来的最小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个。
/**
* 函数说明: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的思想。
留给小伙伴们来练手实现!