软件质量之路:测试驱动开发

发表于:2008-2-22 15:48

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:网络转载

        测试不能够证明错误不存在,只能够证明错误存在。尽可能测试一切可以测试的东西。
测试是如何驱动开发过程的

        测试驱动开发起源于XP法中提倡的测试优先实践。测试优先实践重视单元测试,强调程序员除了编写代码,还应该编写单元测试代码。在开发的顺序上,它改变了以往先编写代码,再编写测试的过程,而采用先编写测试,再编写代码来满足测试的方法。这种方法在实际中能够起到非常好的效果,使得测试工作不仅仅是单纯的测试,而成为设计的一部分。为什么这么说呢?

        在编写程序之前,每个人都会先进行设计的工作。可能有些人的设计比较正式,绘制模型,编写文档。有些人的设计只是存在于脑海之中。且不论是设计是精细还是粗糙,你都为随后的编码活动制定了一个标准。这个标准的明确程度和你的设计的细致程度有关。但应该承认,这个标准是不够细化的。因为你的设计不可能精细到代码级的程度。而标准不够明确的则会产生一些问题,例如,在编写代码的过程中,你还可能会发现原先的设计出现问题,从而中途改变代码的编写思路。这将会导致成果难以检验,进度难以度量。

        既然以设计为导向的标准不够明确,不够具体。那什么样的标准才是合适的呢?只能是代码。因为代码是最明确、最具体的。所以测试优先的本质其实是目标管理。编写测试代码其实是在制定一个小目标。这个小目标非常的明确,它规定了你需要设计的类、方法。以及方法需要满足的结果。这些目标制定完成之后,你才开始编写代码来达成该目标。测试的目标要比设计的目标粒度更小,但是成本上却更为经济。其原因有四:

        细粒度的设计需要花费大量的成本,虽然CASE工具都提供了代码自动生成的功能,但结果往往难以令人满意。所以,设计如果要做到和测试相同的粒度,成本不菲,如果粒度不够细,指导的意义又不够。 
        减轻了测试的工作量。无论是否进行设计工作,测试工作都是不可避免的,先进行单元测试,可以减少后续的测试工作量。 
        采用测试优先的过程中,设计的粒度较大。因为测试可以实现一部分的设计工作。这样,设计上可以节省一些工作量。例如,你不再需要将类图细化到每个方法。 
        在编写测试代码上花费的成本,会在回归测试上得到回报。自动化测试的最大好处就是避免代码出现回归。两相权衡,编写测试的代价其实不高。

        你也许会说,我既不进行如此精细的设计,也不事先编写测试代码,这样的成本不是最低吗?请注意,我们的前提是在讨论高质量的软件设计。在一些规模较小或是开发人员能力极强的项目中,确实可以如此办理。但是对于强调质量的大项目,这种处于混沌状态的开发思路是不可取的。

        测试优先是软件开发中一种细粒度的目标管理方法,通过明确的目标,推动软件开发的进行。

        在业界中,采用测试作为评价软件标准的做法是非常常见的。例如,sun公司就专门设计了测试软件,对各个实现J2EE规范的产品进行测试。使用测试作为规范的最大好处就是明确、具体。

        使用测试代码建立目标,编写代码完成测试目标,再制定下一个目标,如此循环,构成了测试驱动开发的工作流程。在接下去的篇幅中,我们开始讨论测试驱动开发中需要注意的一些问题。

测试必须是自动化的

        和自动化测试相对的是手动测试。手动测试有着自动化测试所没有的优势。最明显的就是简单。任何一位开发人员都能够进行手动测试。即便是用户,也很容易掌握手动测试,他们输入数据,并观察软件的反应(输出),从而判断行为是否正确。大部分的手动测试都是对输入和输出的检验,是一个端到端过程,很能说明问题。

        但是手动测试存在的问题比它所带来的好处要多得多。手动测试可能引入错误,人为的输入错误很容易发生,尤其在数据量大的情况下;大量重复性的手动测试可能成本较高,如果考虑软件发生改动而需要重复手动测试的情况,这个成本还会更高;手动测试的覆盖面不广,只能够测试系统的输入和输出;没有办法对组件进行隔离的测试,从而导致发现问题和解决问题的成本都太高。

        基于上面的讨论,我们应该看到,测试应该做到自动化。虽然一开始测试自动化的成本较高,但是从整个的开发过程来看,自动化测试所产生的价值远远超过其成本。
自动化测试的范围

        那么,到底有哪些东西是需要纳入到自动化测试的范围的呢?例如,对于一个典型的分层应用来说,就有数据库层、数据库访问层,业务逻辑层、界面控制层、界面层。这些层次的测试特点各不相同,哪些应该进行自动化测试呢?最理想的情况是全部。测试一切可能是测试的基本原则,让一切测试都变成自动化则是测试驱动开发的准则。

        应该承认,建立自动化测试需要付出成本,有些自动化测试成本较低,有些则较高。例如,对业务方法的自动化测试相对容易,对关联到数据库的业务方法的测试则繁琐一些,因为你需要处理更多的情况。而界面的自动化测试则较困难,因为界面涉及到大量的人机交互,手动测试是非常简单的,但是自动化测试则相当的困难。

        那么,我们就来看看,像界面测试这样的成本高昂的测试需不需要进行自动化呢?我们拿驻留的Web界面来作为人机交互界面的范例。

        首先,按照分层的原则,界面的层次上不应该拥有业务逻辑,界面层负责的事情是收集用户的动作,将用户的动作请求委托给后端的业务层,并对动作进行响应。所以,和业务相关的逻辑已经被剥离到了业务层了。它的自动化测试属于业务层。同时,我们还发现,在测试的推动下,软件的结构变得更加的合理。

        其次,虽然业务逻辑大量的迁移出界面层,但是界面层中还有状态,还有控制逻辑。这些因素都是和界面的控制的表现息息相关的。既然有逻辑,就需要测试。根据MVC的思路,界面层中包含了模型、视图和控制器。模型是对业务层数据的封装,在J2EE的应用中,可能是普通的JavaBean,也可能是离线的数据封装,或是简单的数据集合。视图负责表现模型,而控制器的职责则比较多,它需要负责处理和检查请求参数,负责调用业务对象并传递请求中所包含的数据,负责创建模型,负责生成视图并把模型传递给它。

        所以,在一个真正的MVC界面设计中,测试的重点在于控制器。模型的测试是很容易的,大部分的模型仅仅包含了数据,所以甚至都不需要测试。一个完美的视图,它应该没有包含任何的逻辑,仅仅只是将模型以某种方式表现出来而已。一个设计优秀的视图,可以很容易的进行替换,而不会造成任何的影响。例如,一个JSP视图可以用一个XSLT视图进行替换。所以,结构合理的视图也是不需要测试的(但对页面要素的检查是必要的)。注意,这里的讨论也同样表明,测试驱动设计向合理的方向发展。

        大部分的控制器都是基于servlet技术的,servlet技术是典型的容器内应用,这使得Junit不容易使用。而Cactus能够解决这个问题,它对Junit进行了扩展,提供了大量的预置功能,简化了request、response、session的使用,Cactus通过Redirector Proxy,建立了一个测试客户端和测试服务端模型,来实现基于容器内的测试。下图是典型的Servlet的结构图:

                 dff

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号