为什么要进行烦人的单元测试?

2008-04-09 04:07:55来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

摘要

  这篇文章主要阐述这样一个问题:为什么要进行烦人的单元测试?那些刚刚接触完全测试概念的开发人员常常遇到这个问题。我们这里将采用"反调论证"的方法来回答这个问题, 先提出一些反对单元测试的普遍论点, 然后我们会证明这些论点是站不住脚的。那些公开发表的文章和数据充分证实了单元测试的有效性。

  IPL是一个独立的软件开发机构,成立于1979年,基地设在Bath。IPL在1988年通过了ISO9001认证,并在1991年通过TickIT认证。IPL开发并提供AdaTEST和Cantata等软件验证产品。AdaTEST和Cantata的开发遵循了这些标准的要求。

简介

  在使新的产品和业务的开发过程工业化的尝试中,软件的质量和可靠性常常被看作是薄弱环节。

  在最近的十年里,随着越来越多的人在开发过程中采用了设计方法论和使用CASE工具,软件质量和可靠性的问题越来越受到重视。大多数软件设计人员都接受了这方面的培训,并且在这些正规的软件设计方法的使用中取得了很多经验。

  但不幸的是,软件测试并没有得到同样的重视。很多使用这些软件设计方法的开发活动并没有使软件质量和可靠性得到控制。修改最初的软件开发活动遗留的Bug一般要在软件维护费用中占到50%的比例,这是不正常的,这些Bug应该在有效的软件测试过程中被排除掉。

  这篇文章主要阐述这样一个问题:为什么要进行烦人的单元测试?那些刚刚接触完全测试概念的开发人员常常遇到这个问题。我们这里将采用"反调论证"的方法来回答这个问题,先列出一些反对单元测试的普遍论点,然后我们会证明这些论点是站不住脚的。那些公开发表的文章和数据充分证实了单元测试的有效性。

什么是单元测试

  单元测试是在软件开发过程中要进行的最低级别的测试活动,在单元测试活动中,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

  在一种传统的结构化编程语言中,比如C,要进行测试的单元一般是函数或子过程。在象C 这样的面向对象的语言中, 要进行测试的基本单元是类。对Ada语言来说,开发人员可以选择是在独立的过程和函数,还是在Ada包的级别上进行单元测试。单元测试的原则同样被扩展到第四代语言(4GL)的开发中,在这里基本单元被典型地划分为一个菜单或显示界面。

  单元测试不仅仅是作为无错编码一种辅助手段在一次性的开发过程中使用,单元测试必须是可重复的,无论是在软件修改,或是移植到新的运行环境的过程中。因此,所有的测试都必须在整个软件系统的生命周期中进行维护。

  经常与单元测试联系起来的另外一些开发活动包括代码走读(Code review),静态分析(Static analysis)和动态分析(Dynamic analysis)。静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。动态分析就是通过观察软件运行时的动作,来提供执行跟踪,时间分析,以及测试覆盖度方面的信息。

一些流行的误解

  在明确了什么是单元测试以后,我们可以进行"反调论证"了。在下面的章节里,我们列出了一些反对单元测试的普遍的论点。然后用充分的理由来证明这些论点是不足取的。

它浪费了太多的时间

  一旦编码完成,开发人员总是会迫切希望进行软件的集成工作,这样他们就能够看到实际的系统开始启动工作了。 这在外表上看来是一项明显的进步,而象单元测试这样的活动也许会被看作是通往这个阶段点的道路上的障碍, 推迟了对整个系统进行联调这种真正有意思的工作启动的时间。

  在这种开发步骤中,真实意义上的进步被外表上的进步取代了。系统能够正常工作的可能性是很小的,更多的情况是充满了各式各样的Bug。在实践中,这样一种开发步骤常常会导致这样的结果:软件甚至无法运行。更进一步的结果是大量的时间将被花费在跟踪那些包含在独立单元里的简单的Bug上面,在个别情况下,这些Bug也许是琐碎和微不足道的,但是总的来说,他们会导致在软件集成为一个系统时增加额外的工期, 而且当这个系统投入使用时也无法确保它能够可靠运行。

  在实践工作中,进行了完整计划的单元测试和编写实际的代码所花费的精力大致上是相同的。一旦完成了这些单元测试工作,很多Bug将被纠正,在确信他们手头拥有稳定可靠的部件的情况下,开发人员能够进行更高效的系统集成工作。这才是真实意义上的进步,所以说完整计划下的单元测试是对时间的更高效的利用。而调试人员的不受控和散漫的工作方式只会花费更多的时间而取得很少的好处。

  使用AdaTEST和Cantata这样的支持工具可以使单元测试更加简单和有效。但这不是必须的,单元测试即使是在没有工具支持的情况下也是一项非常有意义的活动。

它仅仅是证明这些代码做了什么

  这是那些没有首先为每个单元编写一个详细的规格说明而直接跳到编码阶段的开发人员提出的一条普遍的抱怨, 当编码完成以后并且面临代码测试任务的时候,他们就阅读这些代码并找出它实际上做了什么,把他们的测试工作基于已经写好的代码的基础上。当然,他们无法证明任何事情。所有的这些测试工作能够表明的事情就是编译器工作正常。是的,他们也许能够抓住(希望能够)罕见的编译器Bug,但是他们能够做的仅仅是这些。

  如果他们首先写好一个详细的规格说明,测试能够以规格说明为基础。代码就能够针对它的规格说明,而不是针对自身进行测试。这样的测试仍然能够抓住编译器的Bug,同时也能找到更多的编码错误,甚至是一些规格说明中的错误。好的规格说明可以使测试的质量更高,所以最后的结论是高质量的测试需要高质量的规格说明。

  在实践中会出现这样的情况: 一个开发人员要面对测试一个单元时只给出单元的代码而没有规格说明这样吃力不讨好的任务。你怎样做才会有更多的收获,而不仅仅是发现编译器的Bug?第一步是理解这个单元原本要做什么, --- 不是它实际上做了什么。 比较有效的方法是倒推出一个概要的规格说明。这个过程的主要输入条件是要阅读那些程序代码和注释, 主要针对这个单元, 及调用它和被它调用的相关代码。画出流程图是非常有帮助的,你可以用手工或使用某种工具。 可以组织对这个概要规格说明的走读(Review),以确保对这个单元的说明没有基本的错误, 有了这种最小程度的代码深层说明,就可以用它来设计单元测试了。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:测试方法和测试工具解决方案(2)

下一篇:系统分析(一)