下面是我准备让开发人员了解的单元测试知识,从而有利于测试人员进行系统测试。不足之处请大家指出!多谢!
认识单元测试
一、单元测试的重要性
单元测试是软件测试的基础,因此单元测试的效果会直接影响到软件的后期测试,最终在很大程度上影响到产品的质量。从如下几个方面就可以看出单元测试的重要性在何处。
时间方面:如果认真的做好了单元测试,在系统集成联调时非常顺利,因此会节约很多时间,反之那些由于因为时间原因不做单元测试或随便做做的则在集成时总会遇到那些本应该在单元测试就能发现的问题,而这种问题在集成时遇到往往很难让开发人员预料到,最后在苦苦寻觅中才发现这是个很低级的错误而在悔恨自己时已经浪费了很多时间,这种时间上的浪费一点都不值得,正所谓得不偿失。
测试效果:根据以往的测试经验来看,单元测试的效果是非常明显的,首先它是测试阶段的基础,做好了单元测试,在做后期的集成测试和系统测试时就很顺利。其次在单元测试过程中能发现一些很深层次的问题,同时还会发现一些很容易发现而在集成测试和系统测试很难发现的问题。再此单元测试关注的范围也特殊,它不仅仅是证明这些代码做了什么,最重要的是代码是如何做的,是否做了它该做的事情而没有做不该做的事情。
测试成本:在单元测试时某些问题就很容易发现,如果在后期的测试中发现问题所花的成本将成倍数上升。比如在单元测试时发现1个问题需要1个小时,则在集成 测试时发现该问题需要2个小时,在系统测试时发现则需要3个小时,同理还有定位问题和解决问题的费用也是成倍数上升的,这就是我们要尽可能早的排除尽可能 多的bug来减少后期成本的因素之一。
产品质量:单元测试的好与坏直接影响到产品的质量,可能就是由于代码中的某一个小错误就导致了整个产品的质量降低一个指标,或者导致更严重的后果,如果我们做好了单元测试这种情况是可以完全避免的。
综上所述,单元测试是构筑产品质量的基石,我们不要因为节约单元测试的时间不做单元测试或随便做而让我们在后期浪费太多的不值得的时间,我们也不愿意因为由于节约那些时间导致开发出来的整个产品失败或重来!
二、单元测试与功能测试比较
单元测试好比房屋建筑现场的建筑监理员,他关心房屋的各个内部系统,如地基、构架、供电系统和管道设备等。房屋每部分工作都安全、正常。单元测试是从开发者的角度来编写的。它们确保类的每个特定方法成功执行一系列特定的任务。每一个测试都要保证对于给定的一个已知的输入应该得到所期望的输出。
功能测试类似于视察同一建筑现场的房主,他假定内部系统将正常运作,并假定建筑监理员在执行其任务。房主关心的是住在这所房子里将会怎样。他关心房子的外观如何,各个房间的大小是否合适,房子能否满足家庭的需要,以及窗户的位置是否有利于采光。
三、单元测试内容和步骤
单元测试的内容
●单元测试的对象是软件设计的最小单位——模块或函数;
●单元测试的依据是详细设计描述,测试者要根据详细设计说明书和源程序清单,了解模块的I/O条件和模块的逻辑结构。
●主要采用白盒测试的测试用例,辅之以黑盒测试的测试用例,使之对任何合理和不合理的输入都能鉴别和响应。要求对所有的局部和全局的数据结构、外部接口和程序代码的关键部分进行桌面检查和代码审查。
●单元测试任务包括:1模块接口测试;2模块局部数据结构测试;3模块边界条件测试;4模块中所有独立执行通路测试;5模块的各条错误处理通路测试。
1、模块接口:模块接口测试是单元测试的基础。只有在数据能正确流入、流出模块的前提下,其他测试才有意义。测试接口正确与否应该考虑下列因素:
1输入的实际参数与形式参数的个数是否相同;
2输入的实际参数与形式参数的属性是否匹配;
3输入的实际参数与形式参数的顺序是否一致;
4调用其他模块时所给实际参数的个数是否与被调模块的形参个数相同;
5调用其他模块时所给实际参数的属性是否与被调模块的形参属性匹配;
6调用其他模块时所给实际参数的量纲是否与被调模块的形参顺序一致;
7调用预定义函数时所用参数的个数、属性和顺序是否正确;
8是否存在与当前入口点无关的参数引用;
9是否修改了只读型参数;
10对全程变量的定义各模块是否一致;
11是否把某些约束作为参数传递。
2、局部数据结构测试:检查局部数据结构是为了保证临时存储在模块内的数据在程序执行过程中完整、正确。局部数据结构往往是错误的根源,应仔细设计测试用例,力求发现下面几类错误:
1检查不正确或不一致的数据类型说明;
2使用尚未赋值或尚未初始化的变量;
3错误的初始值或错误的默认值;
4变量名拼写错误或书写错误;
5不一致的数据类型。
3、独立执行通路:在模块中应对每一条独立执行路径进行测试,单元测试的基本任务是保证模块中每条语句至少执行一次。此时设计测试用例是为了发现因错误计算、不正确的比较和不适当的控制流造成的错误。此时基本路径测试和循环测试是最常用且最有效的测试技术。计算中常见的错误包括:
1误解或用错了算符优先级;
2混合类型运算;
3变量初值错;
4精度不够;
5表达式符号错。
4、错误处理通路:一个好的设计应能预见各种出错条件,并预设各种出错处理通路,出错处理通路同样需要认真测试,测试应着重检查下列问题:
1输出的出错信息难以理解;
2记录的错误与实际遇到的错误不相符;
3在程序自定义的出错处理段运行之前,系统已介入;
4异常处理不当;
5错误陈述中未能提供足够的定位出错信息。
5、边界条件:边界条件测试是单元测试中最后,也是最重要的一项任务。众的周知,软件经常在边界上失效,采用边界值分析技术,针对边界值及其左、右设计测试用例,很有可能发现新的错误。
2、单元测试的步骤
1)理解需求和设计
理解设计是很重要的,特别是要搞清楚被测试模块在整个软件中所处的位置,这对测试的内容将会有很大的影响。需要记住的一个原则就是:好的设计,各模块只负责完成自己的事情,层次与分工是很明确的。在单元测试的时候,可以不用测试不属于被测试模块所负责的功能,以减少测试用例的冗余,集成测试的时候会有机会测试到的。
2)概览源代码
浏览一下源代码,主要任务:
(1)初步检查源代码的编码风格与规范
(2)大致估算测试工作量,比如:需要多少的测试用例、需要写多少的驱动模块和桩模块等。
(3)确定模块的复杂程度,初步制定测试的优先级等。
3) 精读源代码
认真阅读和分析代码,主要任务:
(1)理解代码的业务逻辑。
(2)检查代码与设计是否相符,如果详细设计没有该模块的流程图的话,先去画出流程图。
(3)仔细研究逻辑复杂的模块
(4)可以采用一些检查列表来检查程序可能会出现的问题。如果没有检查列表,那么,可以根据程序的特点,有针对性地检查容易出问题的地方(记得把经验总结下来供下次使用)。
4) 设计测试用例
综合运用白盒测试方法(和结合黑盒测试方法)来设计测试用例,包括功能测试、性能测试等,要达到一定的测试覆盖率。在设计测试用例的过程中,流程图或控制流图是分析的好帮手。
5) 搭建单元测试环境
使用XUnit或自己写的框架将有助于单元测试的实施。在这个阶段主要就是写桩模块和驱动模块,第4步所设计的测试用例是通过驱动模块传递给被测试模块的,然后驱动模块想办法获取被测试模块对数据的处理结果,并判定返回的实际结果与测试用例的预期结果是否一致,通过测试框架来记录执行的结果,对于出现的错误,还需要统计错误的信息,供执行完之后分析。
搭建单元测试环境要避免在main函数中使用printf和scanf函数来跟测试人员交互来达到获取测试用例数据的信息。这样的测试还是没有摆脱手工测试方式,效率是低下的。同时,对于测试结果是否通过测试也不要使用printf方式打印被测试函数的返回结果值,避免要人工去检查结果。
6) 执行测试
运行写好的驱动模块完成对被测试模块的测试。
7) 补充和完善测试用例
单元测试也是个循序渐进的过程,可能一开始考虑的不够全面,或预期的覆盖标准太低,需要在测试过程中不断补充测试用例,直到满足要求为止。
8) 分析结果,给出评价
根据测试的结果分析、查找错误的原因,并找到解决的办法。测试结束之后,根据测试过程的数据统计,给出被测试对象评价