求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
也谈谈测试驱动开发与敏捷
 
发布于2012-5-23
 

看了聊天记录,并看了回复,说说想法吧.....(呜咽中进行....)

Ninputer ,测试驱动开发,本身不是给测试人员用的东西,测试人员如果要进行QA测试,就应该通过robot来进行,好的测试工具有很多,rational里面的那个也不错。像Parasoft的.Test,Compuware的DevPartner等,都是给开发人员用的东西,测试人员尽管也可以用,但实际上用处并不特别大,这是程序员本身的责任,当然,如果不放心程序员,他们提交上来代码后,也可以验证一遍。测试人员的义务应该是在于对软件的用户端的输入与输出进行验证,对于内部逻辑处理应该不进行关注。不过,如果公司管理良好,测试人员水平也足够的话,测试人员是应该进行代码复审的,在此类情况,才有机会用用它们。对于测试驱动开发来说,在代码级别上,这个责任是程序员的,而不是测试人员的。NUnit不是一般意义上的单元测试工具,它已经细化到了函数的级别,测试人员应该关注的是模块级别的。

蝈蝈,商业利益本身与测试驱动开发并无冲突,技术上并无难度,因为代码的完整性及可规约性都是应该事先考虑的,测试驱动开发的成就之处在于,让程序员能够自己有更大程度的控制代码的正确度,相当于提供了两道的代码审核手段,在软件成品的质量上提供了一定的保障。我觉得,它只会减少风险,而不是增加风险。

kwklover,“我能做的就是保证自己写的代码是正确的”,就是测试驱动开发的目的。所以你的行为是完全正确的。但“test完就注释掉”,这个大可不必,你可以用预编译指令来保留上,让Debug的时候,这些代码有效,RELEASE时无效就行了。

然后,谈谈看了聊天记录里的想法吧....(继续呜咽,为什么没有机会参加...)

测试驱动开发,是一种开发的方法,但它本身并不是方法学,也没有什么完整的理论体来保证,它更多的是一种技巧。既然是技巧,那么就是有时候有用,有时不一定要用,几千元的项目,开发人员应该能够掌握软件质量的时候,使用TDD,似乎就大材小用了,同时也浪费时间。这与UML一样,在没有复杂逻辑与并发的情况下,采用它描述系统,无疑是自找麻烦。
  TDD很适合于制作产品和大中型项目,因为它们不同于那种小项目,写完了就可以丢掉,公司以后不一定还会做相同的东西的情况。它更多的意义是能够提供一种开发阶段的验证机制。

测试驱动开发不是为了重构,而是给重构保证了一个可以验证是否正确的方法。因为TDD在使用中,关注的函数的入口与出口,而不是函数的内部逻辑本身,也就是说它只关心正确的输入是出有正确的输出。重构大多数的意义在于改良构架,但往往重构后,开发人员并不清楚,自己重构后导致的后果,这时只要运行一下测试,发现原来的输入与输出集仍然能够通过,就意味着重构的成功,当然这是建立在重构之前,代码运行是通过的基础上的。

在需求发生变化之后,测试代码肯定是要变化的,测试代码本身应该是对非GUI界面的一种测试。因为测试代码本身是用实例来验证功能,也是另一种视角对需求的描述,这就要求结合敏捷开发中的一些理念了。

在敏捷开发中,轻装前进是快乐的事情,但这不意味着丢弃一切模型,一切文档,它在是前期工作做了准备的基础下,正如穿越沙漠一样,如果全身都挂满水壶和食品,是不可能穿越的,但是,要是什么都不挂,估计连回头的机会都没有了。。虽然在现实中,完美的平衡是不可以达到的,但这是可以去追求的方向,至于量的把握,只有看个人经验的总结了。

一般的开发中,都是根据建模的结果来验证代码,代码是否符合模型可以很容易验证,而模型又由谁来验证呢?答案就是TDD了,TDD在这里起到重要但并不关键的作用,它可以对模型进行描述,在写模型的测试代码的时候,因为有仔细地考虑测试的实现,在实际编写中,相当于对模型进行了一次复审,在此就可以找出一些模型上有所矛盾的部分。但为什么说它并不关键?因为TDD是单元性的测试,而不是全局性的测试,要对模型进行验证不但要对细节进行考察,也需要对整体上把握。由于软件开发没有银弹还暂时是一个不争的事实,所以软件的质量保障,还是有许多不可预测的因素在里面,开发人员能够做到的,也暂时仅限于此,毕竟软件开发是团队的事实,从建模到代码撰写都是不可分割的,具体地成功度,就依赖于团队的合作能力了。

对于TDD的覆盖性问题,应该尽量是做到的GUI与后台代码的分离(无论是winform还是asp.net),即使系统慢上一点,我认为也值得(实际上慢不了多少),对于GUI,本身不应该用TDD来进行,这个可以交给测试人员来单独测试,并通过一些工具来减轻工作负担。利用TDD来覆盖全局代码是一个浪费时间的事情,我很不情愿让GUI的测试占去我大量的时间,实际,如果要TDD来驱动GUI的代码编写,很容易造成资源浪费,毕竟在GUI环境下,用手移动鼠标去点击一下,比写一大堆代码来模拟要快乐得多,更何况大量的机器人工具,已经做得很不错了。

测试代码写在什么地方比较好呢?有人愿意写在代码类中,有人愿意另外开一个测试类来写,我的感觉是,想怎么样就怎么样吧,这个是没有规定的。就个人而言,我喜欢在一个方法的旁边写一个测试该方法的测试代码,反正使用了预编译后,RELEASE时不编译进去就行了。

详细说一下我的实践:在类内的内部进行测试时,代码就写在旁边,在类的外部测试时,比如像流程控制,业务规则控制的验证的时候, 尤其是在适当地使用了模式的地方,在模式内的类之间是具有较高的耦合度的,此时如果要测试类的外部调用行为组织而成的功能,那么就在实现此功能的方法旁边写。

Mock虽然好用,但我觉得它在针对数据库的模拟上并不是一个很好的东西,真正要对数据库进行CURD的时候,测试起来是十分困难的,因为你要更多的时候并不是验证SQL语句本身的错误与否,而是要验证你修改的数据是否正确,虽然这可以通过试图构建可测试的代码来解决一些问题,可惜的是,最终的效果,还是要到数据库之中去验证的。

对于这种情况,强烈的建议是,不要使用数据库的MOCK,而应该写一个小的测试程序,在数据库外部使用查询指定的记录,通过一个按钮来显示你需要的数据,这样一边测试你的程序的时候,一边查看数据,就比较容易验证了。

还有,在一些情况下,比较业务规则的验证的时候,使用MOCK也不是一个好主意,因为MOCK对象在使用时,不会有使用的作用,虽然它很轻,但更多的情况下,开发人员还是宁肯重一点,也要保证查看的结果正确,这时,建议采用写直接的实体类,无是DATASET还是DATATABLE,构建越来并不比MOCK的使用更简单时,就可以考虑使用预编译指令,让它们能在DEBUG时生效。正如某位大师所说(是谁不记得了),任何问题都可以引用一个中间层来解决。开发人员,可以写一个代理类并结合预编译指令,让它根据不同的情况,来自动选择究竟是用测试性代码还是真实代码。

很明显,我大量提到了预编译指令,实际上,充分利用它及NUnit.Framework,可以让你将许多觉得麻烦的东西实现得较为简单,我不否认MOCK的重要性及它的意义,我使用它的情况也有,但相对而言还是比较少的。毕竟现在的MOCK框架不能够满足我们的需求,并且会让我们不得不引用新的数据集,很麻烦,有时候不是删除了就可以解决问题。

这里不得不提及一个技巧,因为不断地写预编译指令是一件讨厌的事,所以我修改了模板文件。可以在*\Microsoft Visual Studio .NET 2003\VC#\VC#Wizards\CSharpAddClassWiz\Templates\2052\中找到该模板(这里是中文版的Visual Stuido.net2003),我将它改为以下的代码:

using System;

#if DEBUG

using NUnit.Frameworks;

#endif

namespace [!output SAFE_NAMESPACE_NAME]

{

/// <summary>

/// [!output SAFE_CLASS_NAME] 的摘要说明。

/// </summary>

[TestFixture]

public class [!output SAFE_CLASS_NAME]

{

public [!output SAFE_CLASS_NAME]()

{

        //

        // TODO: 在此处添加构造函数逻辑

        //

}

TDD

}

}

这样,每次添加一个类的时候,自动就有了这些指令,具体的测试代码就可以在#if DEBUG...#endif中进行撰写了。

NUnit是一个很好的工具,但毕竟每次点击它运行都不是一件令人愉快的事情,这里,我是采用了dudu介绍的TestDriven.Net工具,在编译时,可以直接调出NUnit,感觉方便了不少,TestDriver.Net的前身就是NUnit Addin,很不错的玩意。

  NUnit这个工具还有一个比较有意义的地方就是,它能够在程序集里面调用指定的方法,不要小看这个,这是一个横切于代码中,进行代码验证的有效手段。比如说,你的DLL中有一个窗体,你得测试它,如果按一般的方式,你可能为选择把当前的编译出当前的程序集后,在主界面中运行,然后再通过点击N次按钮或菜单,找到你想测试的功能,尽管有robot可以使用,但软件开发人员一般不会自己去装这些玩意在开发中用的,就算用了,我也认为软件开发人员就应该专注于开发,不应该受到其它干扰。

  当然,你也可以先把当前的程序编译成exe,然后再调试。不过,我觉得这还是麻烦,个人的经验是,在测试代码中直接写一个把此窗体显示出来,然后进行操作(虽然这个GUI测试是大多数是测试人员的事,但开发人员总得自己测试一下再给测试人员吧?),就显得十分方便了。


相关文章

微服务测试之单元测试
一篇图文带你了解白盒测试用例设计方法
全面的质量保障体系之回归测试策略
人工智能自动化测试探索
相关文档

自动化接口测试实践之路
jenkins持续集成测试
性能测试诊断分析与优化
性能测试实例
相关课程

持续集成测试最佳实践
自动化测试体系建设与最佳实践
测试架构的构建与应用实践
DevOps时代的测试技术与最佳实践


LoadRunner性能测试基础
软件测试结果分析和质量报告
面向对象软件测试技术研究
设计测试用例的四条原则
功能测试中故障模型的建立
性能测试综述
更多...   


性能测试方法与技术
测试过程与团队管理
LoadRunner进行性能测试
WEB应用的软件测试
手机软件测试
白盒测试方法与技术


某博彩行业 数据库自动化测试
IT服务商 Web安全测试
IT服务商 自动化测试框架
海航股份 单元测试、重构
测试需求分析与测试用例分析
互联网web测试方法与实践
基于Selenium的Web自动化测试
更多...