当前位置: 首页 > news >正文

明晰单元测试

最近,身边的一位朋友因为需要在其单位与同事分享单元测试(Unit Test,UT)方面的知识,邀我对他所准备的PPT进行审阅。在审阅的过程中我发现,他在PPT中指出:“实际工作中,写好程序后对程序功能的调试就是一种单元测试”。由于我知道这位朋友并没有运用单元测试的经验,所以我问到:“你的这一认识是从哪里获得的?”,朋友答曰:“从网上搜来的”。无独有偶,这两天我在微博上看到了对单元测试相似的理解:“写好程序,编译完,跑一跑,看看写得对不对,这就是最简单的UT啊!”
 
对于我这混迹于软件行业超十载,且在工作中能经常娴熟运用单元测试的“老鸟”来说,看到这样的理解实在是hold不住了,觉得很有必要写一篇文章以正视听(希望后面的人能“搜”到这篇文章)。
 
之所以要做“以正视听”这件事,是因为我担心上面的解释让新人或没有单元测试经验的人产生一种幻觉 ——“哇,好赞诶,原来我每天都在做单元测试!”这种幻觉带的后果,是这些人不去做真正的单元测试,且别人在说单元测试如何如何时,他却不知所云。
 
如果要用不会产生争议的文字解释单元测试,我想我不一定能写得比维基百科上的好(点击 这里 ,或许参考我的《 专业嵌入式软件开发 》一书更好),那请允许我从特点的角度对之加以解释。首先,单元测试一定要写测试代码。测试代码并不会最终成为软件产品的一部分,测试代码通过实现各种不同测试用例的方式,检查被测代码(最终成为软件产品的一部分)的行为是否如程序员所希望的那样。读者不难想象,测试用例中需要构建大量被测代码所需的参数、环境等(体力活)。
 
其次,为了简化单元测试程序中测试用例的编写,单元测试一定需要使用一定的测试框架,比如cxxtest、CppUnit、JUnit等等。当然,使用自己设计的测试框架也是一种选择。
 
再次,单元测试通常(我本来想写成“一定”,但又怕被指太绝对)需要通过获取代码覆盖报告这一形式以了解测试效果,来自开源社区的gcov和lcov相信被不少人所知。“代码覆盖”是一个不小的“炸弹”,乃至有的人会选择性地将其看成是“形式主义”。对于有这样反应的人,我相信是因为他们吃过了“代码覆盖”这“鸟”的苦头,因为那帮丫领导将百分百的代码覆盖率当成了考核目标,结果可想而知。
 
代码覆盖报告的真正作用,是帮助程序员了解被测代码的哪些“角落”没有“扫过”,从而指导测试用例的编写。如果一味地以百分百的代码覆盖率作为目标,这会让程序员承担巨大的工作压力。Parasoft(C++ Test工具的开发商)的一份研究报告中指出,覆盖率超过大约80%时,团队所承担的工作压力就很重了,这一报告可作为制定具体覆盖率的参考。
 
另外,即使以百分百的代码覆盖率为实施目标,很遗憾,还是达不到完全保证代码质量的目的,因为测试用例是可以“伪造”的。在软件行业,不论有多么好的软件开发方法,都依赖于程序员的专业精神,否则其效果将大打折扣,这一点对于单元测试也不例外。与其追求百分百的覆盖率,强调测试用例的质量更具意义(OMG,如何保证测试用例的质量?)。还有,千万不要将单元测试当作是“银弹”。
 
抱有“我每天都在做单元测试”幻想的程序员在幻想破灭以后,又会产生另一种错觉 —— “单元测试是测试人员的事”。我得对这类程序员说:“你不负责任”。程序员编写程序后验证其中没有任何缺陷是理所当然的事。什么?你没有遗留缺陷?怎么证明?单元测试!
 
当幻觉与错觉都远离我们以后,或许有的同仁会想:“单元测试就是一种测试!管它什么测试,目的都是为了保证软件质量的,那么在意其具体含义干吗呢?”不,精确掌握各词的具体含义是为了我们能更高效地沟通!想一想,我们还有集成测试、系统测试,为什么要造出这些新词?
 
后注:作者正在准备《软件企业成功实施单元测试的关健因素研究》这一论文,现需进行问卷调查。我写文章给您看,您参与我的问卷调查,算是礼尚往来,如何?问卷位于:
http://www.sojump.com/jq/1423894.aspx 。万分感谢您的参与!
 
 

相关文章:

  • XNA游戏:手势触控
  • 基于corosync和pacemaker实现配置nginx的高可用集群
  • shell文本操作的实际应用
  • 分享memcache和memcached安装过程(转)
  • 域控服务器上安装Lync标准版记录
  • Sqlserver 数据库高级查询和设计
  • 麦肯锡:中国拥有3亿社交媒体用户为全球之最
  • ubuntu下面编译ffmpeg
  • 两个类相互包含对方成员的问题(2)
  • Python运算符重载
  • 五月规划
  • ubuntu 12.04 配置小记
  • java例程练习(图像编程[FramePanel])
  • C/C++左值性精髓(二)哪些表达式是左值,哪些是右值?--- 函数调用表达式和强制转换...
  • 图数据库现状简介
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • Android 架构优化~MVP 架构改造
  • AWS实战 - 利用IAM对S3做访问控制
  • Create React App 使用
  • Java到底能干嘛?
  • JS字符串转数字方法总结
  • Redis学习笔记 - pipline(流水线、管道)
  • Spring Boot快速入门(一):Hello Spring Boot
  • tensorflow学习笔记3——MNIST应用篇
  • vue--为什么data属性必须是一个函数
  • Vue小说阅读器(仿追书神器)
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 浮动相关
  • 给新手的新浪微博 SDK 集成教程【一】
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 我有几个粽子,和一个故事
  • 系统认识JavaScript正则表达式
  • gunicorn工作原理
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​你们这样子,耽误我的工作进度怎么办?
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (13):Silverlight 2 数据与通信之WebRequest
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • ../depcomp: line 571: exec: g++: not found
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .net打印*三角形
  • .NET单元测试
  • .net连接MySQL的方法
  • [ C++ ] STL_list 使用及其模拟实现