请教怎样进行单元测试?(100分)

  • 主题发起人 主题发起人 bllsbgw
  • 开始时间 开始时间
B

bllsbgw

Unregistered / Unconfirmed
GUEST, unregistred user!
单元测试在程序开发的时候是很重要的一环,但是单元测试该怎样进行,
怎样在编写代码的时候,同时书写规范的单元测试代码,该怎样书写单元测试代码?
兄弟我才疏学浅,向各位大富翁请教这个问题,请不吝赐教?分数不多,送上100分请不要嫌少。
 
DUnit
不过我也不会用
 
我也知道用DUNIT,但是我更想了解的是怎样
在程序代码中同时书写单元测试代码,这样,在完成一个功能
或者是完成一个模块以后,我就可以通过单元测试代码对此模块单独进行测试。
据我了解,好的代码是单元测试代码与程序代码共存的,但他们互不影响。
但是我不清楚怎样去书写,所以向大家请教,请大家踊跃发言,分不够可以再加。
 
怎么没有人回答呀,我顶
 
没有人回答吗?我继续顶
 
没有人回答吗?干脆结束算了
 
2002年程序员有一期讲单元测试的,具体哪一期忘了
就是Dunit
 
我也知道2002年程序员杂志有一个专题讨论单元测试的,文章指出:单元测试是一种设计
,我的想法是在没有工具支持的情况下,怎样进行单元测试的设计能使在代码编写阶段
独立进行单元测试。注意,我想要知道的是单元测试设计思想和测试代码编写的规范。
请大家一起来讨论讨论。
为了能更好的讨论,我向大家献上一篇文章,以下文章转自《程序员》杂志:
单元测试
单元测试的角色
在程序设计的领域中有许多种测试,单元测试只是测试中的一种。测试只能找到
程序中的部分错误,难以保证程序完全正确无误,单元测试同样如此。但单元测
试是非常重要的一类测试,它是由程序员自己进行的测试工作。单元测试所测试
的是“程序代码单元是否按照预设的方式执行而产生合乎期待的结果”,也就是
程序代码的正确性。
缺乏测试的程序往往造成恶性循环:缺乏测试的程序代码可能包含许多bug;程
序员在没有测试保护的情况下修改bug,从而引发更多的bug;程序员忙于除虫,
于是更没有时间测试。如此的恶性循环往往导致项目的崩溃。为避免这种恶性
循环产生,程序代码必须有一张安全网来保护。随时进行的单元测试就是这张
安全网。
单元测试提升开发速度及品质
由于软件系统的开发往往受到截止日期的限制,加上需求随时变动,因此往往
很难在预定时间内交付符合质量要求的软件产品。而单元测试则可以帮助程序
员提升速度及品质。
读者可能会想:写程序的时间都不够了,为什么还要程序员编写测试代码?因
为单元测试会带来两方面的收益。首先,频繁的单元测试使程序员能够将排错
的范围缩得很小,从而大大节约排错所需的时间; 其次, 单元测试为重构(refactoring)提供了保障,而重构是提高软件质量的不二法门。所以,投资一定的时间进行单元测试,得到的回报将是更快的开发速度和更高的软件质量。单元测试是一种设计
对于单元测试最新的观念就是:编写单元测试是一种设计的过程。XP ( 极限
编程) 就非常强调“ 测试优先”(test first)的开发过程。在设计阶段,
我们一般并不考虑程序代码如何实现,而是考虑接口及功能。如果同时也考虑“
如何测试”,那么我们考虑的就只是“这些接口提供什么功能”(设计的问题),
而不是这些“功能如何实现”(编码的问题)。所以编写测试也就是一种分析设
计的过程。此外,“测试优先”的方法不但给我们一个良好的设计, 同时也给出
相关的测试代码。有了这些测试代码,程序员可以更快地编写程序,因为他们对
自己的工作更有信心。
理想的开发过程固然不是在程序完成后再一次性编写测试,也不是一开始便把所有
测试编写完成,而是写一点点测试、写一点点程序、再写一点点测试、再写一点点
程序。因为你每次处理的范围都只是一点点,因此更容易处理也更容易把握,程序
代码的品质也会更好。






为什么要进行单元测试
在使新的产品和业务的开发过程工业化的尝试中,软件的质量和可靠性常常被看作
是最薄弱的环节。在最近的十年里,随着越来越多的人在开发过程中采用了设计方
法论和CASE工具, 软件质量和可靠性的问题越来越受到重视。大多数软件设计人
员都接受了这方面的培训,并且在这些正规的软件设计方法的使用中取得了很多经验。
但不幸的是, 软件测试并没有得到同样的重视。很多使用这些软件设计方法的开发
活动并没有使软件质量和可靠性得到控制。修改最初的软件开发活动遗留的Bug一般
要在软件维护费用中占到50%的比例, 这是不正常的, 这些Bug应该在有效的软件
测试过程中被排除掉。
这篇文章主要阐述这样一个问题: 为什么要进行烦人的单元测试? 那些刚刚接触
完全测试概念的开发人员常常遇到这个问题。在这里, 我们将采用“ 反调论证”
的方法来回答这个问题, 先提出一些反对单元测试的普遍论点, 然后再证明这些
论点是站不住脚的。那些公开发表的文章和数据充分证实了单元测试的有效性。
什么是单元测试
单元测试是在软件开发过程中要进行的最低级别的测试活动,在单元测试活动中,
软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
在传统的结构化编程语言( 比如C ) 中, 要进行测试的单元一般是函数或子过程
。在像C++这样的面向对象的语言中, 要进行测试的基本单元是类。对于Ada 语言来说,
开发人员可以选择是在独立的过程和函数还是在A d a包的级别上进行单元测试。
单元测试的原则同样被扩展到第四代语言(4GL) 的开发中,在这里, 基本单元被典型
地划分为一个菜单或显示界面。
单元测试不仅仅是无错编码的一种辅助手段, 也不仅仅在一次性的开发过程中使用。
单元测试必须是可重复的,无论是在软件修改时,还是在移植到新的运行环境的过程中
。因此,所有的测试都必须在整个软件系统的生命周期中进行维护。
经常与单元测试联系起来的另外一些开发活动包括代码复审(Code review ) 、静态分析(Static analysis)和动态分析(Dynamic analysis)。静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。动态分析就是通过观察软件运行时的动作,来提供执行跟踪、时间分析以及测试覆盖度方面的信息。
一些常见的误解
在明确了什么是单元测试以后,我们可以进行“反调论证”了。在下面的章节里,
我们列出了一些反对单元测试的常见论点。然后用充分的理由来证明这些论点是不足取的。

它浪费了太多的时间一旦编码完成,开发人员总是会迫切希望进行软件的集成工作,
这样他们就能够看到实际的系统开始启动工作了。这在表面上看来是一项明显的进步,
而像单元测试这样的活动也许会被看作是通往这个阶段点的道路上的障碍,推迟了对整个
系统进行联调这种真正有意思的工作启动的时间。
在这种开发步骤中,真实意义上的进步被表面上的进步取代了。系统能够正常工作的
可能性是很小的,更多的情况是充满了各式各样的Bug。在实践中,这样一种开发步骤
常常会导致这样的结果:软件甚至无法运行。更进一步的结果是大量的时间将被花费在
跟踪那些包含在独立单元里的简单的Bug上面。单个来看,这些Bug也许是琐碎和微不足
道的;但是总的来说,他们会导致在软件集成为一个系统时增加额外的工期,而且当这个
系统投入使用时也无法确保它能够可靠运行。
在实践工作中, 进行完整的单元测试和编写实际代码所花费的精力大致上是相同的。
一旦完成了这些单元测试工作, 很多Bug将被纠正, 在确信他们手头拥有稳定可靠的
部件的情况下, 开发人员能够进行更高效的系统集成工作。这才是真实意义上的进步,
所以说完整计划下的单元测试是对时的更高效的利用。而调试人员的不受控和散漫的
工作方式只会花费更多的时间而获得很少的好处。
使用AdaTEST和Cantata这样的支持工具可以使单元测试更加简单和有效。但这不是
必须的, 即使是在没有工具支持的情况下, 单元测试也是一项非常有意义的活动。
它仅仅是证明这些代码做了什么这是那些没有首先为每个单元编写一个详细的规格
说明而直接跳到编码阶段的开发人员提出的一条普遍的抱怨。当编码完成、面临代
码测试任务的时候,他们就阅读这些代码, 找出它实际上做了什么, 基于已经写好的
代码进行他们的测试工作。当然, 他们无法证明任何事情。所有的这些测试工作能够
表明的事情就是编译器工作正常。是的, 他们也许能够抓住( 但愿如此) 罕见的
编译器Bug , 但是他们能够做的仅仅是这些。
如果他们首先写好一个详细的规格说明, 测试能够以规格说明为基础, 代码就能够
针对它的规格说明而不是针对自身进行测试。这样的测试仍然能够抓住编译器的Bug,
同时也能找到更多的编码错误, 甚至是一些规格说明中的错误。好的规格说明可以
使测试的质量更高, 所以最后的结论是高质量的测试需要高质量的规格说明。
在实践中会出现这样的情况:一个开发人员要测试一个单元,但是只有单元的代码而
没有规格说明。这是一件吃力不讨好的任务。怎样做才会有更多的收获,而不仅仅是
发现编译器的Bug? 第一步是理解这个单元原本要做什么,而不是它实际上做了什么
。比较有效的方法是倒推出一个概要的规格说明。这个过程的主要输入条件是要阅读
那些程序代码和注释,主要针对这个单元,及调用它和被它调用的相关代码。画出
流程图是非常有帮助的,你可以手工画,也可以使用某种工具。可以组织对这个概要
规格说明的复审(Review),以确保对这个单元的说明没有根本的错误。有了这种最
小程度的代码深层说明,就可以用它来设计单元测试了。
我是个很棒的程序员,是不是可以不进行单元测试?在每个开发组织中都至少有
一个这样的开发人员:他非常擅长于编程, 开发的软件总是一开始就可以正常运行,
因此不需要进行测试。你是否经常听到这样的借口?
在真实世界里, 每个人都会犯错误。即使某个开发人员可以抱着这种态度在很少的一些
简单程序中应付过去, 但真正的软件系统是非常复杂的。真正的软件系统不能寄希望于
没有进行广泛的测试和Bug修改过程就可以正常工作。
编码不是一个可以一次性通过的过程。在真实世界中,软件产品必须得到维护以对需求的
改变作出反应,并且要对最初的开发工作遗留下来的Bug进行修改。你希望依靠那些原始
作者进行修改吗?制造出这些未经测试的原始代码的资深专家们还会继续在其他地方制造
这样的代码。在开发人员做出修改后进行可重复的单元测试,可以避免产生那些令人不快
的作用。
不管怎样, 集成测试将会抓住所有的Bug在前面的讨论中, 我们已经从一个侧面对
这个问题进行了部分的阐述。这个论点不成立的原因在于: 规模越大的代码,集成的复杂
性就越高。如果软件的单元没有事先进行测试, 开发人员很可能会花费大量的时间仅仅是
为了使软件能够运行, 而任何实际的测试方案都无法执行。
一旦软件可以运行了, 开发人员又要面对这样的问题: 在考虑软件全局复杂性的前提下
对每个单元进行全面的测试。这是一件非常困难的事情, 甚至在创造一种单元调用的
测试条件的时候, 要全面地考虑单元被调用时的各种入口参数。在软件集成阶段,
对单元功能全面测试的复杂程度远远超过独立进行的单元测试过程。
最后的结果是: 测试将无法达到它所应该有的全面性。一些缺陷将被遗漏,并且很多
Bug将被忽略过去。让我们打个比方。假设我们要清洗一台已经完全装配好的食物加工
机器, 无论你喷了多少水和清洁剂,一些食物的小碎片还是会粘在机器的死角位置,
只有任其腐烂, 等待以后再想办法。但我们换个角度想想, 如果这台机器是拆开的,
这些死角也许就不存在或者更容易接触到了, 并且每一部分都可以毫不费力地进行清洗。
它的成本效率不高
一个特定的开发组织或软件应用系统的测试水平取决于对那些未发现的Bug的潜在后果的
重视程度。这种后果的严重程度可以从一个Bug引起的小小的不便到发生多次死机的情况。
这种后果可能常常会被软件的开发人员所忽视( 但是用户可不会这样) , 这种情况会
长期损害这些向用户提交带有B u g 的软件的开发组织的信誉, 并且会导致对未来的市
场产生负面的影响。相反地, 一个可靠的软件系统的良好声誉将有助于一个开发组织获
取未来的市场。
很多研究成果表明,无论什么时候作出修改,都要进行完整的回归测试。在生命周期中尽
早对软件产品进行测试将使效率和质量得到最好的保证。Bug发现得越晚, 修改它所需的
费用就越高。因此从经济角度来看,应该尽可能早地查找和修改Bug。在修改费用变得过高
之前, 单元测试是一个在早期抓住Bug的机会。
相比后阶段的测试,单元测试的创建更简单、维护更容易,并且可以更方便地重复。
从全程的费用来考虑,相比起那些复杂且旷日持久的集成测试或是不稳定的软件系统来说,
单元测试所需的费用是很低的。
统计数据
下图摘自《实用软件度量》,它列出了准备测试、执行测试和修改缺陷所花费的时间
( 以一个功能点为基准)。这些数据显示:单元测试的成本效率大约是集成测试的
两倍、系统测试的三倍。
术语“ 域测试” (Field test)意思是在软件投入使用以后,针对某个领域所作的
所有测试活动。这个图表并不表示开发人员不应该进行后阶段的测试活动,这次测试
活动仍然是必须的。它的真正意思是:尽可能早地排除尽可能多的Bug,这可以减少后
阶段测试的费用。
其他的一些图表显示: 高达50%的维护工作量被花在那些总是会有的Bug的修改上面。
如果这些Bug在开发阶段被排除掉的话,这些工作量就可以节省下来。当考虑到软件维
护费用可能会比最初的开发费用高出数倍的时候,这种潜在的对50%软件维护费用的节
省将对整个软件生命周期费用产生重大的影响。
结论
经验表明,一个尽责的单元测试方法将会在软件开发的某个阶段发现很多的B u g , 并且修改它们的成本也很低。在软件开发的后期阶段,Bug的发现和修改将会变得更加困难,并且要消耗大量的时间和开发费用。无论什么时候作出修改,都要进行完整的回归测试。在生命周期中尽早地对软件产品进行测试将使效率和质量得到最好的保证。如果每个开发者都提供经过测试的单元,系统集成过
程将会大大简化。开发人员可以将精力集中在单元之间的交互作用和全局的功能实现上, 而不会陷入充满Bug的单元之中不能自拔。
使测试工作的效力发挥到最大化的关键在于选择正确的测试策略, 这其中包含了单元测试的概念, 以及对测试过程的良好的管理, 还有适当地使用像AdaTEST和Cantata这样的工具来支持测试过程。这些活动可以产生这样的结果: 在花费更低的开发费用的情况下得到更稳定的软件。更进一步的好处是简化了维护过程, 并降低了生命周期的费用。有效的单元测试是推行全局质量文化的一部分, 而这种质量文化将会为软件开发者带来无限的商机。
 
没有人回答的话,请斑竹结束这个贴子吧
 
个人觉得,用DUnit写窗体的单元测试不太合适
单元测试比较适合于功能性的单元中

相对而言,纯面向对象的语言使用单元测试比较流畅,如JAVA
 
顺便说一句,DUnit中有教程和例子可以参考的

比较方便的
 
Dunit 有文档帮助,
看文档操作即可,我就是这样学会的。。。
严格说,Dunit只适合功能涵数的测试....
 
多人接受答案了。
 
后退
顶部