如果不修改类库中的代码,单元测试会报告这三个新的测试都失败了。
小飞对代码做了相应的修改。结果出了这样的错误,见代码清单11-5:
代码清单11-5
Test method UserTest.UserTest.ConstructorTestBlank threw exception System.ArgumentException, but exception System. ArgumentNull- Exception was expected. Exception message: System.Argument- Exception: Value does not fall within the expected range.
大家定睛一看,原来小飞的Copy/Paste用了原来的ArgumentNullExcep- tion,而不是ArgumentException。
如果有人加了下面的代码:
if (!m_email.Contains("@")) { throw new ArgumentException(); } |
这时,代码覆盖测试就会报告代码覆盖率是85%左右。那还得加上新的单元测试以保证所有的代码都得到了基本的测试。
二柱:现在我知道为什么有些软件写了好几年都没有发布了,敢情他们都忙着写单元测试了。
阿超:也许因为他们没有在一开始就写单元测试,所以后来有很多小强要处理。很多调查显示,在软件开发后期发现的Bug,修复起来要花更多的时间。
芸芸:这对我们设计人员有什么用呢?好像都是一些细节的东西。
阿超:在我们写规格说明书(specification)的时候,要越详细越好,最好你的各项要求都可以表达成单元测试的一个测试用例。
芸芸:如果不能表示为一个单元测试呢?
二柱:那就是你写得还不够细。
小飞:我大胆地说一句。如果是一个人写写程序玩玩,单元测试似乎不那么重要。
二柱:你可以大胆地对你的女朋友说:“我们只是玩一玩……”看看效果如何。
阿超:如果玩一玩,什么都不太重要。如果你写的模块会有不同的人,在不同的时间使用,那你最好把你这一“单元”要做的事,以及它不能做的事,用单元测试清晰地表达出来。
2、好的单元测试的标准
下面我们讲讲怎样才算一个好的单元测试。
单元测试应该准确、快速地保证程序基本模块的正确性。下面是验证单元测试好坏的一系列标准:
单元测试应该在最低的功能/参数上验证程序的正确性。
单元测试应该测试程序中最基本的单元——如在C++/C#/Java中的类,在此基础上,可以测试一些系统中最基本的功能点(这些功能点由几个基本类组成),从面向对象的设计原理出发,系统中最基本的功能点也应该由一个类及其方法来表现。单元测试要测试API中的每一个方法及每一个参数。
单元测试必须由最熟悉代码的人(程序的作者)来写。
代码的作者最了解代码的目的、特点和实现的局限性。所以,写单元测试没有比作者更适合的人选了。