谈起单元测试的好处,每个人都能说得头头是道,但真正能将单元测试成功地应用于产品开发的过程中,却难之又难。我所呆的几个公司,以及我从朋友了解到的其它公司,都曾经尝试过采用单元测试来控制软件质量,但到目前为止,我还没有看到一个真正成功的样榜。
我自己在单元测试方面做过三次尝试,一次失败,一次半成功,一次比较成功。试着分析这几次尝试的成败得失的原因,也许能得出普遍而通用的结论。
案例一:
项目名称:
《某水电厂智能短信平台》
项目目标:
从电厂MIS系统的关系数据库中取得实时数据,加工后按照一定规则,通过手机向电厂相关人员发布与生产安全相关的短信。该项目是我到湖南某公司后,接手的一个半拉子项目。该项目已开发了半年多,到了初验收阶段,但用户在使用过程中发现短信系统很不稳定,并提出了许多功能改进意见。我的工作目标是:完善该系统,使之通过用户的验收。
工作过程:
我阅读了该系统的源码后,认为该系统的编码极不严谨,只考虑了常规用例路径,没有各种防误措施。选用的工业MODEM不稳定,经常出现处理异常、假死机、真死机等现象。
我工作的第一步,就更换了底层串口通讯构件,重构了MODEN收发软件模块,在此过程中引入了单元测试,对每一函数都进行了严格的单元测试。
这次引入单元测试是成功的,中途更换工业MODEM的厂家,需要重构短信解析层,因为有单元测试,很快便完成了收敛。该模块的质量也非常高,系统运行至今,底层通讯、短信处理等模块一直非常稳定。
但是,在远程管理平台这一层,我的尝试没有成功,主要原因是因为我对ASP.NET编程极不熟悉,对它的理解、改动非常吃力,更不用说为之增加单元测试模块了。
好在只有系统管理员关心远程管理平台,一般用户不关心这个功能。该项目最后验收通过了。验收之后,该系统也曾出现几次问题,但都是与上层模块有关。
经验:
1. C#开发平台上有一个很好的单元测试工具NUNIT,Visual studio 2003也很好地支持该工具,因此,引入单元测试在技术上没有困难;
2. 我对串口编程比较熟悉,对串口通讯中异常处理的重要性认识得比较深刻,因此,对引入方法以保证系统稳定性的迫切性比较高;
3. 我加入单元测试的几个模块都是底层的模块,这些模块与其它模块的交互性比较小,容易实现单元测试;
4. 单元测试的关键问题是如何将需测试的模块与其它模块隔离,这个系统中需要隔离的是重点是:将实际的串口通讯隔离,我采用了宏替代,并辅以一些模拟函数来模拟串口通讯过程,这个思路很好,实际上就是桩函数的思想;
5. 我对程序防误有一定的经验,因此在设计单元测试用例时比较有针对性;
6. 我在接手该系统前,正在看《单元测试之道 C#篇》,这本书从理论方面给了我很多帮助;
教训:
1. 我对ASP.NET编程极不熟悉,在自己不熟悉的领域也强行推动单元测试,最后的结果非常不理想;
2. 上层模块更需要处理好桩函数和隔离,这一点我经验不足;
3. 单元测试的工作量非常大,我最后放弃在上层模块推行单元测试,便是在项目交付与开发工作量之间权衡后取消的。
待续...