软件测试之单元测试:开发人员的测试
说到单元测试,几乎所有人都知道,由开发人员完成。可是为什么要进行单元测试呢?
开发人员写单元测试的时间几乎和他写产品代码的时间相当,因此,当做项目计划的时候,把单元测试考虑进去是合理的。尽管单元测试增加了相当大的开发工作量,看上去开发时间延长了,但实际上对于一个长期不断改进和维护的项目而言,我们不能忽视级联效应,要从项目整体来看。
单元测试可以保证最基本的缺陷尽早的发现并解决,因此,用来解决被流转到后期的测试阶段的缺陷时间实际上就会缩短。
而如果问开发人员是否进行了单元测试,他们通常也会说,是的,已经做了单元测试。如果问开发人员,他们的单元测试的步骤,答案很可能是:
开发完代码之后,实际运行了程序,简单的做了些功能测试,没有问题
通过断点调试进行了代码跟踪
不得不说,这么做是对的,也都具有一定的价值,但是并未关注到单元测试最核心的价值,那么,什么样的测试是有效的单元测试呢?
有效的单元测试需要编写简单的、自动化的测试代码,并且几乎是和开发代码同时完成的。
开发人员做单元测试不仅必要,而且重要,每个开发人员都有责任对自己开发的代码进行单元测试。
那么,单元测试有哪些特点和作用呢?保证代码质量、更容易发现缺陷、可重复执行、代码更容易维护、解决缺陷的成本更低
为什么单元测试可以更容易发现缺陷?
因为单元测试是在系统的最低级别进行测试,与别的方法或模块进行隔离了,因此单元测试的缺陷要比其他层面的缺陷更容易发现并解决。
进行单元测试最主要的原因之一就是解决缺陷的成本更低,因为单元测试中就解决缺陷是缺陷生成到解决最短的周期。
开发人员眼中的测试——把缺陷扼杀在摇篮里
1. 什么是单元测试?
单元测试是由开发人员在开发产品代码的同时进行的一种独立测试,验证其开发的每个代码单元。
2. 单元测试的目的是什么?
确保程序的逻辑和开发人员对它的预期是一致的。
3. 为什么单元测试应该由开发人员来执行?
对于程序的预期结果,开发人员自己比其他人都要清楚,因此编写有效的单元测试,开发人员本人是最合适的人选。
4. 什么时候进行单元测试呢?
单元测试和开发产品代码应该是同时进行,实际上,引入敏捷开发理论之后,更高的要求是测试驱动开发,即单元测试代码要在产品代码之前编写。
5. 单元测试的单元是什么?测试对象又如何理解?
从实用角度讲,单元通常是指类的成员方法,也可以是任何具有明确功能、规格定义、明确接口定义,且其规模一般比较小的程序代码模块的组合体。
6. 都说单元测试是独立的测试,那么什么是独立测试呢?
独立,是指将代码从原始程序中隔离出来,尽可能地与程序其他部分或者外界以来隔离,针对各个单元单独进行测试。
到这里,做个小的总结来把握单元测试的关键点:
a. 单元测试记录预期的行为
b. 每个单元测试针对一个单独的行为进行测试
c. 尽可能地与程序其他部分或外界依赖隔离
d. 一旦失败,可以清楚地定位失败的原因
e. 可以重复运行,且每次运行都有确定的行为,不受上一次运行的影响
f. 可以快速地执行(10秒左右),简单、实用、高效
g. 有效的单元测试是自动化的
通过以上的介绍,可以对单元测试有了大概的了解,单元测试是什么,为什么要进行单元测试,但是,单元测试需要覆盖的内容有哪些呢?单元测试,作为白盒而进行的测试,测试包括主要的流程和出错的分支,以及边界条件,使用代码量来衡量测试的覆盖率。
1. 单元测试的测什么?
单元测试需要保证:覆盖到所有新开发的代码、修改过的代码以及存在的受影响的代码。
a. 覆盖代码所有分支,包括正常路径和错误路径
b. 覆盖所有有效的输入/输出情况
c. 覆盖所有无效的或预期以外的输入/输出情况
d. 覆盖所有的日志文件和返回代码
e. 如果有出错恢复步骤,确保其正确性
f. 验证代码的逻辑正确
g. 在虚拟翻译的构建环境中通过测试
h. 对敏感代码要测试其性能(可能需要描述代码路径及对数据库的访问)
i. 单元测试需要在开发环境中完成
j. 修改所有可翻译的代码片段,确保其正确
2. 单元测试的流程?
设计文档--设计单元测试--创建/修改代码和相关文档--对新开发代码或者修改代码进行单元测试--代码审核--集成到代码存储库
3. 单元测试开始的标志?
当接收到一份新的设计文档或者一个缺陷后,就需要开始考虑单元测试了。
4. 单元测试结束的标志?
代码完成,解决了已知的问题或已提出解决遗留问题的下一步计划,且经过代码审核及执行通过单元测试后集成至代码存储库中。
5. 审核单元测试报告:
手动的单元测试报告需要有详细的步骤,包括使用到的数据集
自动化的单元测试报告不仅要有运行结果,还要给出描述,说明这一组单元测试所测的是哪一部分代码
接下来了解下测试驱动开发(TDD)
TDD每次针对一个很小的功能点,通常是小到一个单独的方法。
1. TDD流程:
a. 在实现新功能之前,先考虑代码的使用需求(包括功能、过程、接口等),为其编写测试代码
b. 让新写的测试代码和已有的测试代码一起运行
c. 为新功能编写最少的实现代码
d. 再次让新测试代码和已有的测试代码一起运行,根据运行结果修改实现代码,直到测试全部通过
e. 在此过程中,积极地对待代码重构,使底层设计和实现更加优化,使接口更加简单
f. 重复以上步骤
对TDD的总结:设计代码-->编写代码-->代码不可运行-->可运行-->重构
2. TDD的目的?
不是为了验证代码的实现,而是为了描述一段代码的用途和用法的设计规格说明,这种描述是无二义的,是可执行验证的。
3. TDD的优势在哪里?
TDD要求测试优先,因此可以使得代码天生具有可测性,也因此保证了几乎100%的单元测试覆盖,代码中的缺陷密度低,有利于更早地发现缺陷,方便调试。
TDD最大的好处,不是最终得到单元测试资产,也不是使单元测试全部通过,而是通过不断对代码进行重构,而最终从设计层面对代码做出改进。
4. TDD与敏捷开发的关系总结: