单元测试环境及过程
单元测试环境
单元测试环境的建立是单元测试工作进行的前提和基础,在测试过程中起到的作用不言而喻。单元测试环境并不一定是系统投入使用后所需的真实环境,可采用模拟环境。
由于一个模块或一个方法(Method)不是一个独立的程序,在测试时要考虑它和外界的联系,因此要用到一些辅助模块来模拟与所测模块相联系的其它模块。辅助模块分两种:
驱动模块:相当于所测模块的主程序。它接收测试数据,把这些数据传送给所测模块,最后再输出实际测试结果。
桩模块:代替所测模块的子模块。桩模块可进行少量数据操作,根据需要实现或代替子模块的部分功能。
那么所测模块和与它相关的驱动模块及桩模块共同构成一个“测试环境”,如下图所示。为了能够正确的测试软件,驱动模块和桩模块的编写特别是桩模块,可能需要模拟实际子模块的功能,因此桩模块的开发就不是很轻松。我们常常希望驱动模块和桩模块的开发工作比较简单,实际开销相对低些。
对于每一个包或子系统可根据编写的测试用例编写一个测试模块类做驱动模块,用于测试包中所有待测试模块。最好不要在每个类中用一个测试函数的方法,应测试跟踪类中所有的方法。这样的好处在于:
1.能够同时测试包中所有方法或模块,也方便测试跟踪。
2.联合使用所有测试用例对同一段代码执行测试,发现问题。
3.便于回归测试,当某个模块作修改后,只要执行测试类就可以执行所有被测的模块或方法,及时发现修改引进的错误。
4.复用测试方法,保持测试单元持久性和复用性。
5.测试代码与产品代码分开,代码更简洁清晰,提高可维护性。
单元测试涉及到的测试技术通常有:
针对被测单元需求的功能测试、用于代码评审和代码走读的静态测试、白盒测试和非功能测试。
为了提高单元测试的质量,只了解这些单元测试技术还远远不够,还要选择合适的测试策略。在选择测试策略时,主要考虑如下4种方式:
1.自顶向下(Top Down Unit Testing)的单元测试策略;
2.自底向上的单元测试策略(Bottom up Unit Testing);
3.孤立的单元测试策略(Isolation Unit Testing);
4.综合测试策略。
单元测试过程
单元测试的主要过程如下:
1.详细设计说明书(规约)通过评审,单元测试进入准则。
2.编制单元测试计划。
3.编制子系统单元测试计划(如果有并且需要)。
4.编写测试代码并开发单元测试用例。
5.代码审查 6.测试用例评审
7.测试执行 8.缺陷提交
9.缺陷跟踪
10.测试报告及评审,单元测试退出准则。
单元测试任务
对于方法或类来说,我们很难发现所有可能出问题的地方,找到所有潜藏的bug。经验丰富的人常常能轻松的分析出系统最可能出现的问题,但是没经验或经验很少的工作人员很难做到。可是,最终用户在使用过程中迟早会发现程序中遗留的bug。测试时一般可以从以下几个方面着手,即:
1.判断得到的结果是否正确?
对于测试而言,首要的任务就是查看一下所期望的结果是否正确,即对结果进行验证。这些简单的测试,可根据需求说明进行。
假如没有明确的文档,可以询问相关人员确定一些需求或者安排用户参与以便及时获得反馈对确定的需求进行调整在整个软件开发生命周期中,需求更新可能使判断代码是否“正确”的标准改变。对于那些涉及大量测试数据的测试,读者可考虑使用一个独立的数据文件存储这些数据,单元测试是直接读取这些并仔细检查,以免引入不必要的错误,并想尽各种办法确认结果的正确性。
2.判断是否满足所有的边界条件?
边界条件是指软件计划的操作界限所在的边缘条件。边界条件测试是单元测试中最后也是最重要的一项任务。
众所周知,软件经常在边界上失效,采用边界值分析技术,针对边界值及其左、右设计测试用例很有可能发现错误。边界上的错误常常防不胜防,在使用边界值测试的方法时,不妨结合实际项目参考以下测试技巧:
①输入完全伪造或者和要求不一致的数据,如:给程序提供一个根本就不存在的文件或路径。
②输入一个格式错误的数据,如:softwaretesting@sohu没有顶层域名的电子邮件地址。
③提供一个空值或者不完整的值(如:null和0.0)
④与正常值相差很远的值,例如:把人员年龄输入为10000岁。
⑤假如一个列表中不允许有重复的数值存在,就可以给它传入一组存在重复数值的列表;如果某个字段的值要求唯一,那么可以输入两个或多个相同的数值来进行测试。
⑥如果要求按照一定的顺序来存储一些数据,那么可以输入一些顺序打乱的数据来做测试。
⑦对于一些做了安全限制的部分,尽量通过各种途径尝试能否绕过安全限制的测试。
⑧如果功能的启用有一定的顺序限制,就用和期望不一致的顺序来进行测试。
此外可能还会存在更多边界值情况,有的书把边界值测试归纳为六种情形,即:一致性(实际数值是否和预期一致)、顺序性(实际数值是否像预期那样有序或者无序)、区间性(实际值是否位于合理最小值和最大值内)、依赖性(代码是否引用不在代码控制范围内的外部资源)、存在性(实际数值是否非null、非0)、基数性(是否有足够值)、
3.分析能否使用反向关联检查?
在实际程序中,有一些方法可以使用反向逻辑关系来验证。但要注意原方法和它反向测试中的错误可能会同时掩盖一些bug。所以,可能的话尽量使用不同方法来做反向测试。
4.分析是否能使用其他手段来交叉检查一下结果?
一般而言,对某个值进行计算会有一种以上的算法,但我们会因考虑到运行效率或其他方面的原因而选择其中一种。那么可以使用剩下算法中的一个进行交叉检查来进行测试。当然也可以利用升级前实现同样功能的代码来检查新版本。
5.分析是否可以强制一些错误发生?
在实际使用过程当中,总会有意想不到的情况和错误发生。如果某个方法依赖于网络、数据库或servlet引擎等,那么就可以模拟这些外部条件产生错误的情况做单元测试。
6.分析模块接口
数据在接口处出错就像丢了进入大门的钥匙,无法进行下一步工作,只有在数据能正确流入、流出模块的前提下,测试才有意义。测试接口正确与否应该考虑下列因素:
(1)输入的实际参数与形式参数的个数是否相同;
(2)输入的实际参数与形式参数的属性(数据类型)是否匹配;
(3)输入的实际参数与形式参数的量纲(数量级,取值范围) 是否一致;
(4)调用其它模块时所给实际参数的个数是否与被调模块的形参个数相同;
(5)调用其它模块时实际参数属性是否与被调模块形参属性匹配;
(6)调用其它模块时实际参数量纲是否与被调模块的形参量纲一致;
(7)调用预定义函数时所用参数个数、属性和次序是否正确;
(8)是否存在与当前入口点无关的参数引用;
(9)是否修改了只读型参数;
(10)对全程变量的定义各模块是否一致;
(11)是否把某些约束作为参数传递。
7.分析局部数据结构
局部数据结构往往是错误的根源,对其检查主要是为了保证临时存储在模块内的数据在程序执行过程中完整、正确,因此应仔细设计测试用例,力求发现下面几类错误:
- 被测模块中是否存在不合适或不一致的数据类型说明;
- 被测模块中是否残留未赋值或未初始化的变量;
- 被测模块中是否存在错误初始值或错误默认值;
- 被测模块中是否有不正确变量名(拼错或不正确截断);
- 被测模块中是否存在数据结构不一致;
- 被测模块中是否会出现上溢、下溢和地址异常。
8.分析独立路径
在模块中应对每一条独立路径进行测试,单元测试是保证模块中每条语句至少执行一次。此时设计测试用例是为了发现因计算错误、比较不正确和控制流不适当造成的错误,最常用且最有效的测试技术是基本路径测试。
常见的错误通常包括:
①运算符优先级理解或使用错误;
②混合类型运算错误;
③变量初始化错误;
④精度不够;
⑤表达式符号错误。
9.分析出错处理是否正确
好的设计应能预见各种出错条件并进行适当出错处理,即预设出错处理通路。出错处理是模块功能的一部分,带有预见性的机制保证在程序出错时,对出错部分及时修补,因此出错处理通路同样需要认真测试,此类测试应着重检查:
- 输出的出错信息是否易于理解;
- 错误陈述中能否提供足够的定位出错信息;
- 显示错误与实际遇到的错误是否相符;
- 异常处理是否得当;
- 在程序进行出错处理前,错误条件是否已引发系统的干预。
125jz网原创文章。发布者:江山如画,转载请注明出处:http://www.125jz.com/1671.html