程序员为什么不写单元测试?

发表于:2008-4-18 13:30  作者:未知   来源:网络转载

字体: | 上一篇 | 下一篇 |我要投稿 | 推荐标签:

2、业务逻辑简单,不值得编写单元测试

        程序员是聪明的,程序员也总是自认为是聪明的。认为一些业务逻辑比较简单的类不必要编写单元测试。我们必须承认,需求不断变化,我们也必须要有勇气去接受需求变化。编写单元测试的另一个目的就是拥抱变化,而不是拒绝变化。编写单元测试就是提高了我们对程序的信心。

        在敏捷软件开发中,代码为项目组所有成员所有,项目组的任何一个人都可以去修改任何一个代码文件。每当我要去修改一个别人编写的代码时,我总是多么的希望有程序的单元测试代码,往往都让我非常的失望。一般我都得花费很大的力气去猜想作者的原始意图。也许你会说:“你可以去看需求文档啊!你不会去看注释吗?”。但实际情况是,当需求文档完成了它的使命后,开发人员就把它扔到了一边了,文档总是过期的。没有几个项目组能够使得需求,设计这些文档与最新实现代码保持一致。所以去看一个过期的文档是没有价值的。注释也同样,保持最新仍然是一个最大的问题,并且注释能够提供的信息是非常有限的。所以我最需要的就是看测试代码了。测试代码最能反映出方法最新的功能契约。由代码的编写者去写的单元测试要比由其它人去编写的单元测试要更完善、更准确。

        很多问题恰恰就出在一些我们认为简单的代码中。除非是像一个JavaBean的getter和setter方法,因为这些方法可以通过IDE自动代码生成,没有必要为它编写测试。

        在项目开发中,我们需要经常通过重构来优化代码及改进我们的设计,当我们对代码进行重构之后,怎么能够保证代码仍然是正常的?那就是运行所有被修改的代码的测试。如果测试通过,则说明我们的重构是正确。

        我们不能回避代码的维护问题。代码维护包括修正bug和增加功能。维护工作可能会距离代码编写完成有很长一段时间。当需要修改一个bug而修改了代码,或增加一个新的功能而修改了代码时,又怎么能够保证修改后的代码仍然是正确的和没有隐患的呢?

        也许你会说,发布到应该服务器去测试就知道了。笔者曾经发生过因为维护而导致了更严重问题发生的情况。一个系统在生产环境正常运行很长时间了。某一天,业务人员要求修改某一个功能,笔者按业务的要求实现了要修改的功能,业务也测试了修改后的功能,然后发布到了生产环境。程序下发两个星期后,报了一个非常严重的生产问题上来,以前能够正常运行的功能突然有问题了,导致了大量的生产数据错误。这个问题是非常致命的,只能暂时停用系统。

        最后我查明原因是,出错的模块与上次修改的代码有关联,上次修改时没有同时去修改现在出错的模块。要是我能够在修改代码后,运行所有的测试类,测试就肯定会报告不通过。也就不会把隐藏有这么严重错误的程序下发到生产环境去。

        我们看看没有写单元测试是怎么进行集成的。如果某些结果与我们所期望的不一致时,我们可能会在程序中加上许多print语句,然后通过控制台来监视程序的运行过程。采用print语句并不能够保证我们的程序的正确性。最好的情况是,它只能保证一条正确的路径,不能保证其它的分支。另外当太多的print语句的信息在控制台上,也会让我们看不到想看到的信息——控制台的信息是有限的。在开发测试时,把调试信息打印在控制台还可以接受,但是在生产环境,如果还有调试信息出现在控制台,那是绝对不可以接受的。我们经常会忘记把调试的print语句及时的删除掉,从而影响程序的性能。最关键的是,print语句不能保证程序的正确性,也不能为你节省开发的时间。只会给你带来负面的影响。

3、不知道怎么编写单元测试

        如果你相信单元测试的价值,那么去学习如何编写单元测试最终会让你获益的。

        以Java开发为例,junit这样的单元测试组件是非常易于学习和使用的。其它语言也有类似的单元测试组件。要相信这将是简单和能为你带来价值的。笔者见过许多程序员编写单元测试,但是编写的单元测试完全没有起到它应有的作用,这也与不知道怎么编写单元测试有关。所以我们应该掌握一些编写单元测试的基本原则:

        •为什么编写测试:虽然我们说为所有的代类都编写单元测试,但是测试JavaBean的setter或getter方法无异于是自寻烦恼。编写这样的测试完全是浪费时间,而且还增加了维护的困难。

        •学会使用断言:断言就是让我们为方法设置一个期望值。当方法执行结果与期望值不一致时,测试组件就会报告测试不通过。我见过一些项目的单元测试不是使用断言,而是自己编写一个打印(println)工具类,可以详细的在控制台中打印出类的详细成员信息及集合的详细信息。

        在单元测试中使用这个打印工具类来打印输出结果。这看起来好像非常不错。但是不应该使用这种方式来编写单元测试使用打印工具类,需要程序员自已从控制台去观察程序的执行结果。当输出信息非常多时,控制台信息是无法向上翻屏的。所以不能够给我们提供更多的信息。所以这种方法也不能用于自动化测试。

        使用打印工具类造成了一种假像,测试报告我们的测试总是成功的!如果使用断言,当方法的执行结果与我们设置的期望值不一致时,则会详细的报告测试失败的情况。

        使用打印工具来代替断言,造成测试的不充分,只会写出一个低测试覆盖率的测试。我们需要一个充分的测试。

        •最大化测试覆盖率:我们除了测试一个正确的路径外,还需要测试方法的每一个分支逻辑。需要编写尽可能多的测试程序代码的测试。写一个充分的测试。

        •避免重复的测试代码:测试类也是非常重要的,与应用代码一样。测试类包含的重复代码越多,测试类自身出现的错误也会越多。而我们需要做的编码工作也就越多。

        • 不要依赖于测试方法的执行顺序:使用Junit来进行单元测试,它不能保证测试方法按照我们的意图的顺序来执行。当一个测试类有多个测试方法时,我们不能让一个测试方法必须在某一个测试之后执行才能成功。Junit不能为我们做这样的保证,我们不能依赖于测试方法的执行顺序。

        •针对接口测试:我们有“针对接口编程”的OO设计原则。同样对于测试,我们也需要针对接口测试。也就是说在编写单元测试时,测试对象总是使用接口,而不是使用具体类。


43/4<1234>

评 论

  • lovetesting52 (2008-4-23 11:04:57)

    国内现在对测试还是比较重视的,相信在不久的将来很多公司都会重视单元测试。

  • windone (2008-4-18 17:20:09)

    单元测试的效益和花费的时间人力相比太低,这是国内一直难以推广的主要原因

  • chech28 (2008-4-18 17:07:28)

    据我所知赛门铁克肯定做单元测试,而且这个误杀,单元测试是测不出来的。

论坛新帖

顶部 底部


建议使用IE 6.0以上浏览器,800×600以上分辨率,法律顾问:上海信义律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2021, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号

51Testing官方微信

51Testing官方微博

扫一扫 测试知识全知道