单元测试-【转】论单元测试的重要性

本文章转自:http://www.51testing.com/html/00/n-3724000.html ,只供学习使用。

系列导航

点击跳转到系列博文目录导航

1 什么是单元测试

单元测试是对软件组成单元进行测试,其目的是检验软件基本组成单位的正确性,测试的对象是软件设计的最小单位:函数。(维基百科)

2 单元测试不是集成测试

这里需要强调一个观念,那就是单元测试只是测试一个方法单元,它不是测试一整个流程。举个例子来说,一个Login页面,上面有两个输入框和一个button。两个输入框分别用于输入用户名和密码。点击button以后,有一个UserManager会去执行performlogin操作,然后将结果返回,更新页面。

那么我们给这个东西做单元测试的时候,不是测这一整个login流程。这种整个流程的测试:给两个输入框设置正确的用户名和密码,点击login button, 最后页面得到更新。叫做集成测试,而不是单元测试。当然,集成测试也是有他的必要性的,然而这不是我们每个程序员应该花多少精力所在的地方。在这方面,有一个理论叫做Test Pyramid,如下图所示:
在这里插入图片描述
Test Pyramid理论基本大意是,单元测试是基础,是我们应该花绝大多数时间去写的部分,而集成测试等应该是金字塔上面能看见的那一小部分。

为什么是这样呢?因为集成测试设置起来很麻烦,运行起来很慢,发现的bug少,在保证代码质量、改善代码设计方面更起不到任何作用,因此它的重要程度并不是那么高,也无法将它纳入我们正常的工作流程中。

而单元测试则刚好相反,它运行速度超快,能发现的bug更多,在开发时能引导更好的代码设计,在重构时能保证重构的正确性,因此它能保证我们的代码在一个比较高的质量水平上。同时因为运行速度快,我们很容易把它纳入到我们正常的开发流程中。

至于为什么集成测试发现的bug少,而单元测试发现的bug多,这里也稍作解释,因为集成测试不能测试到其中每个环节的每个方面,某一个集成测试运行正确了,不代表另一个集成测试也能运行正确。而单元测试会比较完整的测试每个单元的各种不同的状况、临界条件等等。一般来说,如果每一个环节是对的,那么在很大的概率上,整个流程就是对的。虽然不能保证整个流程100%一定是对的。所以,集成测试需要有,但应该是少量,单元测试是我们应该花重点去做的事情。

很多时候大家会把单元测试跟集成测试搞混, 其实只要记住单元测试面向的对象是最小程序单元: 函数,它是面向软件应用开发者而言的, 而集成测试一般是面向测试人员进行黑盒测试的,不是开发者重点关注的地方。

3 为什么很多人不写单元测试

网上有些文章关于这个问题做了一些讨论, 我把原因贴出来:

  • 不知道怎么编写单元测试
  • 单元测试价值不高,完全是浪费时间
  • 业务逻辑比较简单,不值得编写单元测试

说实话,在着手去看单元测试之前,上面的原因我基本上也都存在,相信很多人跟我有同样的想法.
但是细看这些原因归根结底就是不了解单元测试,下面根据网上的文章和我自己理解去反驳这些观点.
1:不知道怎么编写单元测试
  这肯定是没有接触过单元测试,根本不了解单元测试会带给你什么,你能从中得到什么益处. 设想一下,当你开发完一个功能模块的时候,你如何确定你的模块没有 bug 呢?如果涉及到具体的业务,你会执行 debug 模式,然后一点一点的深入到代码中去查看吗?如果你一直都是这样,那么你早就已经 OUT 了。赶快去了解一下单元测试的工具吧,你会收获很大的。这在Android开发中更是非常"蛋疼"的,每次项目编译执行少则2-3分钟,多则可能十几分钟,如果每次都是真机调试会耽误大量的时间在上面.
2:单元测试价值不高,完全是浪费时间
  这种说法其实是错误的。为什么这么说呢?在日常的开发中,代码的完工其实并不等于开发的完工。如果没有单元测试,那么如何保证代码能够正常运行呢?测试人员做的只是业务上的集成测试,也就是黑盒测试,对单个的方法是没有办法测试的,而且,测试出的 bug 的范围也会很广,根本不能确定 bug 的范围,还得去花时间来确定 bug 出在什么地方。难道这就不浪费时间了吗?甚至,这样的方式,时间浪费的会更多。
3:业务逻辑比较简单,不值得编写单元测试
  所谓的业务逻辑比较简单,其实是相对的。当你对某一块业务逻辑很熟悉的时候,你自然会认为它很简单。然而,单元测试的必要性并不是仅仅在于测试代码的功能是否正确,还在于,当其他同事在了解你的业务的时候,能够很快的通过单元测试来熟悉代码的功能,甚至不用去读代码,就能够知道它做了哪些事情。因此,写单元测试不仅是解放了自己,更方便了别人。

4 TDD 测试驱动开发

在这里插入图片描述
  Test-Driven Development, 测试驱动开发, 是敏捷开发的一项核心实践和技术,也是一种设计方法论。TDD原理是开发功能代码之前,先编写测试用例代码,然后针对测试用例编写功能代码,使其能够通过。由于TDD对开发人员要求非常高,跟传统开发思维不一样,因此实施起来相当困难。
  测试驱动开发有好处也有坏处。因为每个测试用例都是根据需求来的,或者说把一个大需求分解成若干小需求编写测试用例,所以测试用例写出来后,开发者写的执行代码,必须满足测试用例。如果测试不通过,则修改执行代码,直到测试用例通过。
  好处,通过测试的执行代码,肯定满足需求,而且有助于接口编程,降低代码耦合,也极大降低bug出现几率(如果是极限编程,几乎是不可能有bug)。
  坏处,1.投入开发资源(时间和精力);2.由于测试用例在未进行代码设计前写;很有可能限制开发者对代码整体设计
  Note: 个人认为我们也没有必要完全按照TDD模式进行开发, 但是这种思想是需要我们借鉴的,在有很多复杂逻辑处理的地方应用这种开发模式还是非常有必要的.

5 单元测试工具

既然单元测试如此重要,那我们使用哪种单元测试工具呢?
对于pure Java代码来说, 采用JUnit做基础的单元测试框架, Mockito用来mock对象等,AssertJ丰富断言支持等。

展开阅读全文

传统的单元测试和面向对象的单元测试

03-05

这是我从前写的一篇关于单元测试的文章其中的一节。希望对大家有所帮助rn访问我的网站 www.oodiscovery.comrnrn......rn传统的单元测试和面向对象的单元测试rn 在过去使用编写面向过程方式编写程序时,人们依然运用自己的智慧总结出代码复用的的方法。通常程序员会把实现相同功能的代码放在一起,做成一个函数;将一个或几个逻辑功能独立并且相似或相关的函数组织在一个文件当中。当客户程序需要使用已经定义的函数时,只要将需要的文件include进来就可以了。这是通常的做法。rn 在做这样的单元测试时我们只要编写一段客户代码,然后调用相关文件中的函数。通过定义不同的前置条件,就可以验证每个单元是否符合他的说明要求。如果通过了单元测试,却在集成的时候出现问题,大多数情况下是接口实现出现了错误,测试的重点往往集中在集成测试而不是单元内部实现的测试。rn 现在,绝大多数的软件组织都选用了C++,Java, VB(尽管VB的面向对象性不是很好,但还是可以算在面向对象程序语言范畴之内)等面向对象的程序语言来进行开发。面向对象思想的引入,改变了过去的编程习惯。我们不再用“文件”这种硬概念来组织逻辑代码,而是开始使用“类”这种软概念。类逐渐成为独立功能代码片断的集合体,也就成了面向对象程序的基本单位。设计良好的类是功能代码的良好集成。因此,现代的单元测试逐渐演化成为对类的测试。rn 类测试与传统单元测试相比较有很多不同的地方,这些不同源于面向对象与面向过程的不同。一个类可以有一个或者很多个实例。而且在一定条件下,实例与实例之间可以相互作用,相互通讯。这种复杂性增加了类测试的难度。对于一些简单的类,我们可以使用类似传统单元测试的方法,但是高级的类就要求测试人员对系统的整个体系有一个比较完整的认识,只有这样,构造出来的测试环境才能够适应被测试的类。对于一些比较复杂的对象作用,编写测试环境代码有时候非常困难。对于测试人员来说,完成测试环境需要的开发时间甚至远远超过程序实现的时间。这个时候我们必须要么对程序设计进行修改,要么放弃针对这个类的测试。rn 测试人员的工作就是要证明开发人员的代码是否符合要求,要完成这一点在必要的时候要构建测试容器。但是构建测试容器是需要成本的,而这一点往往是管理人员经常忽略的。rn......rn 论坛

没有更多推荐了,返回首页