作为一个合格的程序员,写相关代码的单元测试是最基本的要求,但是提到测试,又有多少程序员知道各种测试的区别和 怎么写好一个单元测试,为什么要写单元测试呢,这篇文章就是这些问题的一个扫盲吧,参考相关人员的文章,作为自己学习的一个笔记。
一.先普及一下测试方法 常用测试方法:
(一)按是否查看程序内部结构分为:
1、黑盒测试(Black Box Testing):
黑盒测试是根据软件的规格对软件进行的测试,这类测试不考虑软件内部的运作原理,因此软件对用户来说就像一个黑盒子。简单来说,这种测试只关心输入和输出的结果,并不考虑程序的源代码。黑盒测试分为功能测试和性能测试:
1)功能测试(function testing),是黑盒测试的一方面,它检查实际软件的功能是否符合用户的需求。包括逻辑功能测试、界面测试、易用性测试和兼容性测试。
2)性能测试(performance testing),软件的性能主要有时间性能和空间性能两种。其中,时间性能主要指软件的一个具体事务的响应时间,而空间性能主要指软件运行时所消耗的系统资源。
2、白盒测试(White Box Testing):
白盒测试是把测试对象看作一个打开的盒子。利用白盒测试法进行动态测试时,需要测试软件产品的内部结构和处理过程,不需测试软件产品的功能。与黑盒测试相反,这种测试就要研究程序里面的源代码和程序结构。
(二)按是否运行程序分为
1、静态测试(static testing):
静态测试指测试不运行的部分,只是静态地检查程序代码、界面或文档可能存在的错误的过程。例如测试产品说明书,对此进行检查和审阅.。
2、动态测试(dynamic testing):
动态测试是指通过运行软件来检验软件的动态行为和运行结果的正确性。具体操作就是输入相应的测试数据,检查输出结果和预期结果是否相符的过程。
( 三)、按阶段分为:
1、单元测试(Unit Testing):
单元测试是最微小规模的测试,测试的是某个功能或代码块。典型地由程序员而非测试员来做,因为它需要知道内部程序设计和编码的细节知识。
2、集成测试(Integration Testing):
集成测试是指一个应用系统的各个部件的联合测试,以决定他们能否在一起共同工作并没有冲突。部件可以是代码块、独立的应用、网络上的客户端或服务器端程序。这种类型的测试尤其与客户服务器和分布式系统有关。一般集成测试以前,单元测试需要完成。
3、系统测试(System Testing):
系统测试是将整个软件系统看做一个整体进行测试,包括对功能、性能,以及软件所运行的软硬件环境进行测试
4、验收测试(Accept Testing):
验收测试是基于客户或最终用户的规格书的最终测试,或基于用户一段时间的使用后,看软件是否满足客户要求。一般从功能、用户界面、性能、业务关联性进行测试。
5、回归测试(Regression testing):
回归测试是指在发生修改之后重新测试先前的测试以保证修改的正确性。理论上,软件产生新版本,都需要进行回归测试,验证以前发现和修复的错误是否在新软件版本上再次出现、、、
二 单元测试详解
单元测试与其他测试不同,单元测试可看作是编码工作的一部分,应该由程序员完成,也就是说,经过了单元测试的代码才是已完成的代码,提交产品代码时也要同时提交测试代码。测试部门可以作一定程度的审核。对于程序员来说最关心的就是单元测试了,下面我们详细的说一下单元测试。
1. 基本概念:
单元测试应该仅仅依赖输入,不依赖多余的环境,如果你的单元测试依赖很多环境,那么你可能需要的是集成测试。
2. 相关联
经常与单元测试联系起来的另外一些开发活动包括代码走读,静态分析(Static analysis)和动态分析(Dynamic analysis)。静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。动态分析就是通过观察软件运行时的动作,来提供执行跟踪,时间分析,以及测试覆盖度方面的信息。
3. 什么时候进行单元测试
什么时候测试?单元测试越早越好,早到什么程度?极限编程(Extreme Programming,或简称XP)讲究TDD,即测试驱动开发,先编写测试代码,再进行开发。在实际的工作中,可以不必过分强调先什么后什么,重要的是高效和感觉舒适。从经验来看,先编写产品函数的框架,然后编写测试函数,针对产品函数的功能编写测试用例,然后编写产品函数的代码,每写一个功能点都运行测试,随时补充测试用例。所谓先编写产品函数的框架,是指先编写函数空的实现,有返回值的直接返回一个合适值,编译通过后再编写测试代码,这时,函数名、参数表、返回类型都应该确定下来了,所编写的测试代码以后需修改的可能性比较小。
如果他们首先写好一个详细的规格说明,测试能够以规格说明为基础。代码就能够针对它的规格说明,而不是针对自身进行测试。这样的测试仍然能够抓住编译器的Bug,同时也能找到更多的编码错误,甚至是一些规格说明中的错误。好的规格说明可以使测试的质量更高,所以最后的结论是高质量的测试需要高质量的规格说明。
4. 一个好的单元测试用例设计
单元测试用例的设计方法有很多,不再一一赘述。这里讲讲单元测试用例的设计原则。
a.控制每个用例的检查点数目,最好是一个用例检查一个点;
b.用例之间杜绝数据依赖,或者关联影响;
c.用例不仅要覆盖正确情况,还要测试异常情况,检查函数健壮性;
d.拒绝无谓的断言;
e.用例要尽可能覆盖到较多的逻辑路径,(主要有三种:正常输入,边界输入,非法输入)
f.用例要做到对检查点敏感,在功能失效时候能立即反馈。
g 将test类和产品类代码剥离分开进行。建立测试类
h 将要测试的方法和组件 封装起来 抽离出来会降低测试的难度,尤其是可以提供代码封装性
i 测试代码中不要包含逻辑。不然你咋知道是实现挂了还是你的测试挂了呢?
编码实现单元测试用例的过程中,需要注意一下问题:
a.编码规范性。为了提高程序可读性
b.合适的注释。注释不是越多越好,好的注释旨在提供有用的信息,要清楚明了,避免缩写。建议在函数头加上注释,统一列出函数的功能,输入输出参数,返回值,调用场景等;
c.确保代码和注释的一致性。如果有注释,请在代码变动的同时,维护相应的注释;否则不如没有注释;
d.减少重复代码。比如每个case中都进行数据初始化,检查数据正确性的操作,就可以把这些提取为辅助函数,便于修改和维护;
e.充分使用断言。在用例中,如果对某一点的数据状态不清楚,请用assert.一来,如果有数据异常,可以第一时间定位到;二来,可以避免因为数据问题造成用例崩溃;
f.数据逻辑隔离。可以考虑把用例中的数据和逻辑验证分割开来,既可以方便维护,又使得各个用例清晰易读。
5. 单元测试用例的价值
单测的价值远不止于这种一次性的测试,我们可以:
a.一般性用途:定位问题,验证bug ;
b.回归运行:自动测试,减少手工回归;
c.持续集成:通过累积单测,并在每一次代码变更时,自动运行单测。达成对代码的实时监控和自动测试;
d.扩大覆盖:持续积累单测,可以逐步扩大对当前项目的测试覆盖度;
e.策略参考:每一个case的检查点都是对策略的解读,读懂白盒case,也就明了了代码策略。