基于测试驱动开发的Servlet实现
2018-02-28刘双
刘双
摘要
测试驱动开发是一种极限编程的思想,与传统开发模式不同,测试驱动开发要求测试先行,即先编写测试代码,反向驱动开发的进行。本文介绍测试驱动开发的基本思想及其开发的周期,并与传统开发周期进行比较,最后以Servlet开发为例,使用Junit单元测试工具,实现测试驱动Servlet的开发。
【关键词】测试驱动开发 Servlet 敏捷开发
1 测试驱动开发思想
1.1 敏捷开发
敏捷开发,是一种开发方式,其共有特征是迭代开发,即在系统不断添加更多功能和行为的过程中,微调代码结构,从而演化出能可以经受实践检验的架构。
敏捷开发的另一个特征是以人为驱动,不同于传统的瀑布模型以文档为驱动,敏捷开发注重短时交付,在开发过程中随时与用户沟通,及时调整需求,保证软件质量。
总言之,敏捷开发是一种以人为核心、迭代、循序渐进的开发方式。而测试驱动开发恰恰是敏捷开发的一种特殊实现方式。TDD过程中,会小步前进,每一小步都会产生一个工作良好的产品,每一步都会距离目标更近一些。
1.2 意想编程
测试驱动开发的另一个重要思想是“意想编程”。所谓意想编程,就是写代码前先假设其他部分代码都已经存在了,即使事实并非如此,重点把注意力集中在能有的,而不是己经有的东西上,可以使代码读起来更流畅,更容易理解和使用。
2 TDD开发周期
2.1 测试一>编码一>重构
传统的软件开发生命周期通常包括3个时期,8个阶段,即软件定义时期(问题定义,可行性研究,需求分析),开发时期(总体设计,详细设计,编码,测试),以及维护时期(系统维护),对于开发阶段的周期,可总结为:设计->编码->测试,即先进行设计,然后编码,最后测试。而TDD完全颠覆了传统的开发周期,测试先行,然后编码,最后做设计,即测试->编码->设计。在TDD中,为编码后的设计重新定义了一个名字:重构。故TDD的周期又可总结为:测试一>编码一>重构。
2.2 重构
所谓重构,是一种训练有素,有条不紊的代码清理方式,必须在不改变代码外在行为的情况下,改进程序的内部结构。无论是测试代码,还是程序代码,在完成某个特定功能后,立刻对代码进行清理,在保证代码功能的前提下,删除冗余代码,提取函数,从而改变整个程序的设计。
在TDD的过程中,需要借助XUnit单元测试框架。开发初期,先编写测试代码,此时程序还不存在,仅仅是意想编程,是无法通过测试的,故测试条显示红色,紧接着完善程序代码,保证测试通过,此时测试条变为绿色。因此,TDD的开发周期也可称为:红一>绿一>重构。
3 Servlet基础
3.1 基本概念
Servlet是运行在Web服务器或应用服务器上的程序,作为来自Web浏览器,或其他HTTP客户端的请求和HTTP服务器上的数据库,或应用程序之间的中间层。
3.2 实现方式
Servlet的实现通常有三种方式:
(1)实现Servlet接口;
(2)继承GenerieServlet类;
(3)继承HttpServlet类。
本文采用第三种方式进行设计,对于doPost()/doGet()方法,涉及到两个参数:HttpServletRequest与HttpServletResponse。其中HttpServletRequest,主要用于封装Http请求,把数据保存在request属性中,将数据从一个请求处理组件传递给另一个组件;而参数HttpServletResponse主要用于给客户端回送应答,任何发回给浏览器的bttp头都可以放到response对象中,所有想输出的内容都可以传给应答中的PrintWriter对象和ServletOutputStream对象。
4 测试驱动Servlet开发
下面以10Ginservlet为例,看看TDD是如何实现的。
如前所述,TDD的开发周期是:测试->编码->重构。那么我们首先要进行的是编写测试代码,如下:
HttpServlet Servlet=new LoginServlet();
#使用Mock模拟HttpServletRequest与httpServletResponse,略
Servlet.service(request,response);
assertE quals("/success",response.getRedirectedURL());
編写上述代码时,LoginServlet类并不存在,而是通过意想编程假设LoginServlet类存在service()方法,并调用之,用于验证usemame与password,以及进行页面跳转;另外,在编写测试代码的过程中,需要用到HttpServletRequest与HttpServletResponse的支持,但它们必须在Servlet容器中才能构造出来,为了不影响测试的进行,使用Mock对象模拟它们的行为,被测试模块通过与Mock对象协作,获得一个孤立的测试环境,因此不需要构造上述两个对象,也可以使测试顺利进行。
此时Junit的测试条为红色,为了使测试通过,需完善程序代码,如下:
#获取user,pwd,略
if(isValidLogin(user,pwd)){
response.sendRedirect("/success");
}else{
response.sendRedirect("/Login");
}
实现service()方法,获取参数,进行用户名和密码校验,根据校验结果重定向到相应的页面。
5 总结
综上,本文对测试驱动开发的思想,及其开发周期进行介绍,并通过测试驱动Servlet的开发为例,介绍测试驱动开发技术在正式编码开始前编写测试代码,进而驱动程序的产生,进而保证了代码质量。
参考文献
[1]Lasse Koskela,李贝译.测试驱动开发的艺术[M].人民邮电出版社,2010(11).
[2]陈立群.测试驱动开发在J2EE项目中的全程实践[J].计算机工程与科学,2008,30(04):86-88.