论单元测试的重要性

发表于:2018-1-23 15:42

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:鹿鹿    来源:敲行代码再睡觉

  最近看了几天关于Android单元测试文章, 于是想一边去读一边把学到的东西整理一下,  在真正去介绍单元测试的内容之前,还是非常有必要将单元测试的重要性写一下.
  1 什么是单元测试
  单元测试是对软件组成单元进行测试,其目的是检验软件基本组成单位的正确性,测试的对象是软件设计的最小单位:函数。(维基百科)
  2 单元测试不是集成测试
  这里需要强调一个观念,那就是单元测试只是测试一个方法单元,它不是测试一整个流程。举个例子来说,一个Login页面,上面有两个输入框和一个button。两个输入框分别用于输入用户名和密码。点击button以后,有一个UserManager会去执行performlogin操作,然后将结果返回,更新页面。
  那么我们给这个东西做单元测试的时候,不是测这一整个login流程。这种整个流程的测试:给两个输入框设置正确的用户名和密码,点击login button, 最后页面得到更新。叫做集成测试,而不是单元测试。当然,集成测试也是有他的必要性的,然而这不是我们每个程序员应该花多少精力所在的地方。在这方面,有一个理论叫做Test Pyramid,如下图所示:
  Test Pyramid理论基本大意是,单元测试是基础,是我们应该花绝大多数时间去写的部分,而集成测试等应该是金字塔上面能看见的那一小部分。
  为什么是这样呢?因为集成测试设置起来很麻烦,运行起来很慢,发现的bug少,在保证代码质量、改善代码设计方面更起不到任何作用,因此它的重要程度并不是那么高,也无法将它纳入我们正常的工作流程中。
  而单元测试则刚好相反,它运行速度超快,能发现的bug更多,在开发时能引导更好的代码设计,在重构时能保证重构的正确性,因此它能保证我们的代码在一个比较高的质量水平上。同时因为运行速度快,我们很容易把它纳入到我们正常的开发流程中。
  至于为什么集成测试发现的bug少,而单元测试发现的bug多,这里也稍作解释,因为集成测试不能测试到其中每个环节的每个方面,某一个集成测试运行正确了,不代表另一个集成测试也能运行正确。而单元测试会比较完整的测试每个单元的各种不同的状况、临界条件等等。一般来说,如果每一个环节是对的,那么在很大的概率上,整个流程就是对的。虽然不能保证整个流程100%一定是对的。所以,集成测试需要有,但应该是少量,单元测试是我们应该花重点去做的事情。
  Note: 很多时候大家会把单元测试跟集成测试搞混, 其实只要记住单元测试面向的对象是最小程序单元: 函数,它是面向软件应用开发者而言的, 而集成测试一般是面向测试人员进行黑盒测试的,不是开发者重点关注的地方。
  3 为什么很多人不写单元测试
  网上有些文章关于这个问题做了一些讨论, 我把原因贴出来:
  ●不知道怎么编写单元测试
  ●单元测试价值不高,完全是浪费时间
  ●业务逻辑比较简单,不值得编写单元测试
  说实话,在着手去看单元测试之前,上面的原因我基本上也都存在,相信很多人跟我有同样的想法.
  但是细看这些原因归根结底就是不了解单元测试,下面根据网上的文章和我自己理解去反驳这些观点.
  不知道怎么编写单元测试
  这肯定是没有接触过单元测试,根本不了解单元测试会带给你什么,你能从中得到什么益处. 设想一下,当你开发完一个功能模块的时候,你如何确定你的模块没有 bug 呢?如果涉及到具体的业务,你会执行 debug 模式,然后一点一点的深入到代码中去查看吗?如果你一直都是这样,那么你早就已经 OUT 了。赶快去了解一下单元测试的工具吧,你会收获很大的。这在Android开发中更是非常"蛋疼"的,每次项目编译执行少则2-3分钟,多则可能十几分钟,如果每次都是真机调试会耽误大量的时间在上面.
  单元测试价值不高,完全是浪费时间
  这种说法其实是错误的。为什么这么说呢?在日常的开发中,代码的完工其实并不等于开发的完工。如果没有单元测试,那么如何保证代码能够正常运行呢?测试人员做的只是业务上的集成测试,也就是黑盒测试,对单个的方法是没有办法测试的,而且,测试出的 bug 的范围也会很广,根本不能确定 bug 的范围,还得去花时间来确定 bug 出在什么地方。难道这就不浪费时间了吗?甚至,这样的方式,时间浪费的会更多。
  业务逻辑比较简单,不值得编写单元测试
  所谓的业务逻辑比较简单,其实是相对的。当你对某一块业务逻辑很熟悉的时候,你自然会认为它很简单。然而,单元测试的必要性并不是仅仅在于测试代码的功能是否正确,还在于,当其他同事在了解你的业务的时候,能够很快的通过单元测试来熟悉代码的功能,甚至不用去读代码,就能够知道它做了哪些事情。因此,写单元测试不仅是解放了自己,更方便了别人。
  4 TDD 测试驱动开发
  Test-Driven Development, 测试驱动开发, 是敏捷开发的一项核心实践和技术,也是一种设计方法论。TDD原理是开发功能代码之前,先编写测试用例代码,然后针对测试用例编写功能代码,使其能够通过。由于TDD对开发人员要求非常高,跟传统开发思维不一样,因此实施起来相当困难。
  测试驱动开发有好处也有坏处。因为每个测试用例都是根据需求来的,或者说把一个大需求分解成若干小需求编写测试用例,所以测试用例写出来后,开发者写的执行代码,必须满足测试用例。如果测试不通过,则修改执行代码,直到测试用例通过。
  好处,通过测试的执行代码,肯定满足需求,而且有助于接口编程,降低代码耦合,也极大降低bug出现几率(如果是极限编程,几乎是不可能有bug)。
  坏处,1.投入开发资源(时间和精力);2.由于测试用例在未进行代码设计前写;很有可能限制开发者对代码整体设计
  Note: 个人认为我们也没有必要完全按照TDD模式进行开发, 但是这种思想是需要我们借鉴的,在有很多复杂逻辑处理的地方应用这种开发模式还是非常有必要的.
  5 单元测试工具
  既然单元测试如此重要,那我们使用哪种单元测试工具呢?
  对于pure Java代码来说, 采用JUnit做基础的单元测试框架, Mockito用来mock对象并采用Dragger2进行依赖注入。
  所以后面的文章将介绍下面内容:
  ●JUnit单元测试基础框架
  ●Mockito  mock框架
  ●Dragger2 dependency框架
  特别的, 对于Android中的单元测试, 我们将使用到Robolectric框架实现JVM上调用Android中的类。

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号