最近一直都在做测试用例设计,主要是针对服务器端的业务进行测试,除了编写测试用例,实现接口的自动化测试外,还需要对核心代码段进行走读,然后查漏补缺测试用例。其中也有了不少的收获,想着还是把它们先记录下来吧,往后有新的想法还可以继续修改或者增加。今天总结的比值类测试分解,先说明下比值类需求大概意思就是:A/B的这类小需求点,首先我会以最近我测试遇到的实例为例,然后慢慢给出实际测试过程中我的一些经典总结。
提取出来的需求是这样的:服务器之间流量的比值判断,每台服务器给其定义一个流量阀值(服务器的配置文件中),这个阀值就是这台服务器的最高流量值了。然后有一个当前流量值,就是获取当前系统的下载流量值,流量比值就是当前流量值与流量阀值的比较(当前流量值/流量阀值)值。现在就是需要对服务器间的流量比值进行测试;会怎样设计测试用例呢?
有觉得这个需求好像没啥可测的童鞋么?嘿嘿,当初我就觉得好像也没啥可测性,不就一个除法么,貌似看着不需要多加分析神马?流量阀值是保存在配置文件中的,默认值非0,如果运维童鞋硬是写了0导致服务器出问题,那应该是他们自己的责任,当前流量值是直接从服务器上获取下载流量值然后在数据库中,判断流量比值的时,就是拿这2个值进行比较罢了,况且流量比值只是一个算法(就是选择一台最优服务器)中的一部分,当时就把时间放在算法的业务逻辑上了。而后针对算法设计测试用例后就开始先进行手工测试了,针对这个忽略的需求点,大致也以下2个测试用例:
1. 设置服务器A: 流量阀值为102400,当前流量为3000;服务器B: 流量阀值为102400,当前流量为2000, 有时候算法选了A服务器,有时候执行又是选了B服务器;
2. 设置服务器A: 流量阀值为102400,当前流量为204800;服务器B: 流量阀值为102400,当前流量为307200, 结果正确,选了A。
开发哥哥修改一遍后,测试不通过,修改第二遍才通过。oh mygod!如此一个简单的除法,怎么会酱紫~~开发解释一通后,看了下代码(c++),才造不是简单的/ 和比较大小的事情,开始觉得自己漏掉的神马~~~
流量阀值是int类型的,当前流量值存在数据库也是一个int类型的,开发哥哥没有进行处理,直接相除。这样如果是3000/102400=0;2000/102400=0 除出来的结果都是0了,所以就相等了;后将分子(当前流量)转换成double后,发现还是比较不了,还是会出现同一个条件随机选择服务器的结果,这是因为对比值大小比较时未进行精度控制,当两个比值相差很小的时候,比如相差为0.0001的时候,不同的服务器可能会给出不同的结果,精度大于0.0001的服务器能做出正确的判断,而小于0.0001的,会随机生成不足的位数,导致比较结果也出现随机。
得知这些结果后,暗自偷笑了一把,若是当时设置测试数据时,随手设置流量阀值为10,设置当前流量巧妙的设置成其倍数等,会有多少bug会因此未被测试出来。后面回头一想,这何尝不是思维的不严谨的一种表现呢,这个需求实际就是比值类需求,就是两个数相除,测试经常会强调,发散思维的思考;但是实际上的此类发散,我觉得是在严谨的逻辑思维后再居于此类的发散,是一种有规律的发散,而不是毫无根据的随意发散。最后看了下测试结果完全正确后的该部分的代码,如下所示:
static FS_INT32 FlowRatioCompare(ServiceInstanceStateItem &a, ServiceInstanceStateItem &b) { double a_ratio, b_ratio; FS_INT32 ret; // avoid taking 0 as divisor if (a.stServiceInstanceState.nFlowrateOverloadThreshold == 0) { a.stServiceInstanceState.nFlowrateOverloadThreshold = 1UL; } if (b.stServiceInstanceState.nFlowrateOverloadThreshold == 0) { b.stServiceInstanceState.nFlowrateOverloadThreshold = 1UL; } a_ratio = (double)a.stServiceInstanceState.nUploadRate / a.stServiceInstanceState.nFlowrateOverloadThreshold; b_ratio = (double)b.stServiceInstanceState.nUploadRate / b.stServiceInstanceState.nFlowrateOverloadThreshold; // FLT_EPSILON = 1.19209290E-07F defined in float.h if (fabs(a_ratio - b_ratio) < FLT_EPSILON) { ret = 0; } else if (a_ratio - b_ratio > FLT_EPSILON) { ret = 1; } else { ret = -1; } return ret; }
函数FlowRatioCompare的入参是需要比较的两台服务器的对象的引用,主要做了三件事:
A. 首先就是对每台机器的阀值进行了判断,毕竟是要做被除数的,如果出现运维误配导致生产线上机器崩溃此类重大问题,还是很不应该的,如果阀值是0,则给其赋予一个非0的值。
B. 接着就是对其进行除法比较了,之前学习了python,知道python中除法就有2个相关概念,一个叫Floor Division(17//3=5;17//3.0=5.0),还有一种叫Classic Division(17/3=5;17/3.0=5.66666667), 对c++来说就只有/ 一个操作符,也就只有Classic Division,如果两个都是int类,16/3和17/3的结果是一样的,就都会是5.所以应该把其中一个除数转换成double类型后相除就能得到小数点后面的位数了。
C. 最后对两个浮点数比较时的精度问题考虑。明确给出精度的大小值,如果两个浮点数相减的绝对值比精度值还小,表示两个数相差很近,这时程序判断两者就是一样的;否则就表示两个浮点数相除较远,就可以正常判断大小了。
了解正常的处理逻辑后,再做比值类测试,至少要考虑以下几点:
A. 分子,分母单位一致么?(本实例均为kbit/s)
B. 分子为0,怎么办?
C. 分子,分母是什么类型的数据?需求是Classic Division,还是Floor Division?
D. 浮点数值比较时,如果处理其精度问题?
为此,增加下面测试用例(假设精度为小数点后2位):
1. 设置服务器A: 流量阀值为100,当前流量为200;服务器B: 流量阀值为100,当前流量为100,A 比值:2;B比值:1 ,此类情况下,流量比值:A > B
2. 设置服务器A: 流量阀值为500,当前流量为120;服务器B: 流量阀值为500,当前流量为120 ,A 比值:0.24;B比值:0.24.由于当前精度保证为小数点后2位,此类情况下,流量比值:A = B
3. 设置服务器A: 流量阀值为500,当前流量为120;服务器B: 流量阀值为400,当前流量为100 ,A 比值:0.24;B比值:0.25.由于当前精度保证为小数点后2位,此类情况下,流量比值:A < B
4. 设置服务器A: 流量阀值为500,当前流量为312;服务器B: 流量阀值为800,当前流量为500,A比值:0.624;B比值:0.625.由于当前精度保证为小数点后2位,此类情况下,流量比值:A = B
5. 设置服务器A: 流量阀值为0
有没有觉得这样摸清逻辑思路后再写测试用例,好像思路也大开了感觉,虽然这类小需求是测试常见的需求,但是弄清原理对测试来说是非常重要的,再此基础上,结合实际的业务,可以发撒出更多的测试用例。其他类的测试需求分解总结后面会陆续补上,未完待续~~