从测试角度对测试驱动开发的思考
测试驱动开发(TDD)是极限编程的重要特点,它以不断的测试推动代码的开发,既简化了代码,又保证了软件质量。本文主要从测试角度出发,从需求分解等四个阶段阐述了测试人员在测试驱动开发中所发挥的促进作用
大家都知道,软件生命周期一般分为六个阶段:制定计划、需求分析、设计、编码、测试、运行和维护。在软件工程中,这个复杂的过程用软件开发模型来描述和表示,常见的软件开发模型有:瀑布模型、螺旋模型、V模型、W模型等。而这些传统的开发模型都以开发为主,测试常常扮演的是一个亡羊补牢的配角,这类开发模型已渐渐的不能满足现在项目组的需要。从而诞生了比较实用的、高效的、以测试为中心的软件过程开发方法—测试驱动开发(TDD)。
测试驱动开发,其基本思路就是通过测试来推动整个开发过程。在整个软件开发流程中,让测试先行,如将测试方案设计工作提前、将编写一小段的测试代码或产品代码提前、同时将测试方案当作开发行为的准绳,然后在软件后续的开发过程中实时进行验证,最终实现软件开发过程的“小步快走”。
且看下面两个泥瓦匠的工作方法:
工匠1:先拉上一根水平线,砌每一块砖时,都与这根水平线进行比较,使得每一块砖都保持水平;
工匠2:先将一排砖都砌完,然后拉上一根水平线,看看哪些砖有问题,再进行调整。
作为旁观者,你肯定也会觉得工匠1的方法要科学一些,的确如此。在软件项目中,在“砌砖”时以“水平线”为标准,是不是会降低开发与需求理解的偏差、降低开发过程中的缺陷率、并还会提高bug定位速度呢?答案当然是肯定的。
在软件整个过程中融入测试驱动开发,那到底从哪些阶段去驱动呢,从测试角度来看,我个人认为可以从需求分解、单元测试、集成测试、系统测试四个阶段来进行。
一、需求分解阶段
需求是软件开发的源头,无论是新开发项目还是持续迭代更新的项目,开发人员在开发功能和测试人员在进行测试的时候,都需要最先确定需求。
在需求发布到需求分析、需求理解及需求确认这一过程中,往往会出现以下现象:
(1)需求经常变更,在正在开发过程中突然需求又变了;
(2)需求理解偏差,开发或测试对需求理解的角度不同,会出现各种理解偏差;
(3)需求描述模糊或过于简单,开发人员和测试人员会分别花费较多时间去找产品人员确认需求;
(4)测试人员往往对需求的理解只停留在用户的角度,未深入从代码的角度去
思考,如该功能包含的边界范围、接口、异常情况、对其他函数或类的影响等等;
试想,如果能尽可能的避免上述现象的发生,那不就打响了测试驱动开发的“第一炮”了么?我认为从以下几个方面来进行,或许有些效果:
(1)测试人员、开发人员和产品共同参与需求的评审、更改、确认;
(2)测试人员对较大的需求(非简单的页面展示)进行分解成一个个小的功能点,编写成一个个小的产品代码(即所谓的测试用例),从而避免因为需求理解不一致导致偏差的问题,如下面是一个酒店相关需求产品代码的示例:
(3)明确需求后,先预估本次需求对系统其他功能有没有附作用,把风险降到最低;
二、单元测试阶段
测试驱动开发的基本思想就是在开发功能代码之前,先编写测试代码。这是一个非常精典的理论,但是在实际项目过程中,这样实现可能会有一定的难度。既然有难度,那你还写这篇文章干嘛?请不要这样问我,我会很无奈,因为我只是一个菜鸟,菜鸟所理解的测试驱动开发肯定不能和专家的观点相提并论。
在此,我们还是先来回顾下软件开发模型中的W模型:
由图可以看出,W模型的主要特点是测试伴随着整个开发的生命周期,但其缺点就是把软件的开发视为需求、设计、编码等一系列串行的活动,无法支持迭代、自发性以及变更调整。
这种自上而下的只适合那种比较稳定、需求变更较少的大型项目(如军工项目、第三方测试机构测试项目),而不适用于需求变更频繁、迭代较快的项目,产品人员提供需求后,就会快速进入编码实现阶段,其中会省略了概要设计和详细设计两步。
那通过什么方式可以替代概要设计和详细设计两阶段?
试想一下,测试人员通过下面两种方式来进行弥补,是否有利于测试驱动开发呢?
步骤1:编写单元测试计划,明确测试目标
测试计划主要内容包括:
* 主要功能模块,及实现功能定义
* 测试时间、人员分配
* 每个模块包含哪些测试类型、测试方法
* 明确每个功能模块所属的类名、函数名和新添加字段(由开发完成)
* 测试用例(需求分解阶段的产品代码)
步骤2:测试人员在开发编码完成后进行单元测试
前提:
(1)测试人员与开发人员对接
(2)测试人员搭建开发环境,并熟悉代码结构
(3) 步骤1中的测试计划,都得测试人员和开发人员共同评审通过,并作为测试的标准
单元测试检查点:
(1)静态测试:检查代码语法、每个类代码行数等是否符合研发规范
(2)动态测试:运用junit测试框架,根据测试用例,检查每个函数输入输出的
正确性、代码分支覆盖率、异常处理等等
三、集成测试阶段
集成测试,即是对代码进行封装之后,对每一个功能模块进行的测试。
对于测试人员来说,在集成测试阶段又如何能发挥自己的作用,有效的做到测试驱动开发呢?
先来看下集成测试前提条件:编码完成—>单元测试通过—>发布代码,部署成功—>集成测试。
所以测试人员在进行集成测试阶段,以下几方面我认为有利于测试驱动开发:
(1)测试人员熟悉开发环境,熟悉代码内部结构,能运用测试思维,提前预估风险,规避部分测试风险;
(2)对部分难模拟场景,测试人员可以自己通过更改代码或配置,模拟相应测
试场景,喊少开发的工作量;
(3)测试人员在测试过程中发现bug之后,能快速定位bug,并能初步判断bug
引起原因,对开发更改bug减少跟踪时间;
四、系统测试阶段
系统测试,即是通过所有功能模块的相互连接,对整个系统进行连调测试。
在系统测试阶段,测试人员在测试驱动开发中又起到一个什么样的促进作用呢?
因为在前几个阶段,测试人员逐步参与需求理解、开发环境搭建、单元测试、集成测试,所有在系统测试阶段,测试人员有以下几个优势:
(1)对整个系统内部结构比较明了,对功能也很熟悉,能用较少的时间完成测试
(2)对不同功能之间调用的接口比较熟悉,在对系统进行接口方面的测试时有一定的优势
(3)若在测试过程中出现了环境问题,作为测试人员也会快速找到问题或解决方案
(4)测试人员可针对系统特定的功能点,精准的编写和优化自动化测试框架,
从而在以后的系统测试阶段,更加节约了人力成本和发现bug的效率
(5)通过对系统的理解,能在系统需要进行安全测试、压力测试时快速展开工作
以上几个测试阶段便是个人从测试角度对测试驱动开发的理解,本文所理解的测试驱动开发参考Kent Beck所著的《Test-Driven De velopment》,仅供参考!