白盒测试又叫结构测试,透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试是一种测试用例设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,你清楚盒子内部的东西以及里面是如何运作的,通过分析程序的内部结构和逻辑来设计测试用例。
测试程序:
“找零钱最佳组合”程序 : 假设商店货品价格都不大于100元(且为整数),若顾客付款在100元内,现有一个程序能在每位顾客付款后给出找零钱的最佳组合(找给顾客货币张数最少)。 假定此商店的货币面值只包括:50元、20元、 10元、 5元、2元、1元 六种。
一、判定/条件覆盖(CDC)
判定/条件覆盖(CDC)要求测试用例覆盖每个条件的真和假,以确保所有的判定和条件的每种可能性都被测试到。
1.主程序流程图:
负责判定有效输入的函数为get_input(),重要的条件句也在该函数中。在该函数中需要分析的是4个条件语句的判定。
2.get_input()流程图:
3.四个条件语句的判定:
33 if not len(input_str.split()) == 2:
37 if (not price.isdigit()) or (not receive.isdigit()):
42 if (not 0 <= price <= 100) or (not 0 <= receive <= 100):
45 if price > receive:
判定中的每一个条件取到两种可能的值,具体情况如下:
| 判定 | 条件 | 真 | 假 | ||
|---|---|---|---|---|---|
| 33 | len(input_str.split()) == 2 | len(input_str.split()) == 2 | len(input_str.split()) != 2 | ||
| 37 | price.isdigit() | price是整数 | price不是整数 | ||
| 37 | receive.isdigit() | receive是整数 | receive不是整数 | ||
| 42 | 0 <= price <= 100 | 0 <= price <= 100 | price<0 | price >100 | |
| 42 | 0 <= receive <= 100 | 0 <= receive <= 100 | receive<0 | receive >100 | |
| 45 | receive > price | receive > price | receive<=price |
4.测试用例设计
| 例 | 输入 | 输出 |
|---|---|---|
| 1 | 1 1 1 | 提示错误信息:'请输入两个整数, 以空格分隔: ' |
| 2 | 33.3 44 | 提示错误信息:'请输入整数: ' |
| 3 | 33 44.4 | 提示错误信息:'请输入整数: ' |
| 4 | 33.3 44.4 | 提示错误信息:'请输入整数: ' |
| 5 | 101 101 | 提示错误信息:'请输入0-100之间的整数: ' |
| 6 | 101 100 | 提示错误信息:'请输入0-100之间的整数: ' |
| 7 | 100 101 | 提示错误信息:'请输入0-100之间的整数: ' |
| 8 | 60 50 | 提示错误信息:'顾客实付款应大于商品总价,请重新输入: ' |
| 9 | 50 100 | 最佳找零组合 |
5.执行结果分析
| 例 | 输入 | 输出 |
|---|---|---|
| 1 | 1 1 1 | |
| 2 | 33.3 44 | |
| 3 | 33 44.4 | |
| 4 | 33.3 44.4 | |
| 5 | 101 101 | |
| 6 | 101 100 | |
| 7 | 100 101 | |
| 8 | 60 50 | |
| 9 | 50 100 |
分析得,执行结果符合预期。
二、 基本路径覆盖(BPC)
基本路径覆盖(BPC)要求测试用例覆盖程序中的每条可能的路径,以确保每个路径都被执行到。
1.画出对应的控制流图
流图:一种简单的控制流表示方法,对程序流程图简化后得到,更突出表示程序控制流的结构。复合条件表达式需要改成一系列只有但条件的嵌套判断。
获得有效输入get_input()函数如下:
# 获取有效输入
def get_input():
print('请依次输入商品总价以及顾客实付款(均为0-100之间的整数,以空格分开): ')
while (True):
input_str = input()
if not len(input_str.split()) == 2:
print('请输入两个整数, 以空格分隔: ')
continue
price, receive = input_str.split()
if (not price.isdigit()) or (not receive.isdigit()):
print('请输入整数: ')
continue
price = int(price)
receive = int(receive)
if (not 0 <= price <= 100) or (not 0 <= receive <= 100):
print('请输入0-100之间的整数: ')
continue
if price > receive:
print('顾客实付款应大于商品总价,请重新输入: ')
continue
break
return price, receive
控制流图如下:
2.计算圈复杂度(环路复杂度)
该度量用于计算程序的基本的独立路径数目。
1)流图中区域的数量对应与环形的复杂性
2)给定流图的圈复杂度 V(G) = E(边数) - N(节点数) + 2
3)给定流图的圈复杂度 V(G) = P(判定节点的数量) + 1 ,判定节点(谓词界定)是包含条件的节点
对应流图中的圈复杂度,计算如下:
- 流图中有 7 个区域
- V(G) = 20条边 - 15节点 +2 = 7
- V(G) = 6个判定节点 + 1 =7
3.测试用例设计
根据上面的计算方法,可得出7个独立的路径。
- 路径1:4-5-6-7-8-5
- 路径2:4-5-6-9-10.a-11-12-5
- 路径3:4-5-6-9-10.a-10.b-11-12-5
- 路径4:4-5-6-9-10.a-10.b-13-14-15.a-16-17-5
- 路径5:4-5-6-9-10.a-10.b-13-14-15.a-15.b-16-17-5
- 路径6:4-5-6-9-10.a-10.b-13-14-15.a-15.b-18-19-20-5
- 路径7:4-5-6-9-10.a-10.b-13-14-15.a-15.b-18-21-22
为确保基本路径集中的每一条路径的执行,根据判断结点给出的条件,选择适当的数据以保证某一条路径可以被测试到。
满足上面基本路径集的测试用例是:
| 例 | 输入 | 输出 |
|---|---|---|
| 1 | 1 1 1 | 提示错误信息:'请输入两个整数, 以空格分隔: ' |
| 2 | 33.3 44 | 提示错误信息:'请输入整数: ' |
| 3 | 33 44.4 | 提示错误信息:'请输入整数: ' |
| 4 | 101 100 | 提示错误信息:'请输入0-100之间的整数: ' |
| 5 | 100 101 | 提示错误信息:'请输入0-100之间的整数: ' |
| 6 | 60 50 | 提示错误信息:'顾客实付款应大于商品总价,请重新输入: ' |
| 7 | 50 100 | 最佳找零组合 |
4.执行结果分析
| 例 | 输入 | 输出 |
|---|---|---|
| 1 | 1 1 1 | |
| 2 | 33.3 44 | |
| 3 | 33 44.4 | |
| 4 | 101 100 | |
| 5 | 100 101 | |
| 6 | 60 50 | |
| 7 | 50 100 |
分析得,执行结果符合预期。
附录
找零钱最佳组合源代码:
'''
@Author hty
找零程序
a——50元
b——20元
c——10元
d——5元
e——2元
f——1元
'''
def main():
while (True):
price, receive = get_input()
a, b, c, d, e, f = get_change_plan(price, receive)
print('最佳找零组合为:')
print('50元 %d 张, 20元 %d 张, 10元 %d 张, 5元 %d 张, 2元 %d 张, 1元 %d 张' %(a, b, c, d, e, f))
if if_continue():
continue
else:
break
# 获取有效输入
def get_input():
print('请依次输入商品总价以及顾客实付款(均为0-100之间的整数,以空格分开): ')
while (True):
input_str = input()
if not len(input_str.split()) == 2:
print('请输入两个整数, 以空格分隔: ')
continue
price, receive = input_str.split()
if (not price.isdigit()) or (not receive.isdigit()):
print('请输入整数: ')
continue
price = int(price)
receive = int(receive)
if (not 0 <= price <= 100) or (not 0 <= receive <= 100):
print('请输入0-100之间的整数: ')
continue
if price > receive:
print('顾客实付款应大于商品总价,请重新输入: ')
continue
break
return price, receive
# 计算找零方案
def get_change_plan(price, receive):
change = receive - price
a = change // 50
change = change % 50
b = change // 20
change = change % 20
c = change // 10
change = change % 10
d = change // 5
change = change % 5
e = change // 2
change = change % 2
f = change
return a, b, c, d, e, f
def if_continue():
print("输入 c 继续, 输入 q 退出程序: ")
while(True):
ch = input()
if ch == 'c':
return True
elif ch == 'q':
return False
quitprint("输入无效, 请重新输入: ")
if __name__ == '__main__':
main()