如何写完备的单元测试,写了这些测试给我们带来了什么?

最近在改一个其他公司几年前做的一个信用卡系统,因为年代久远,需求、代码的不全面,导致对同一个问题不断的修改。

需求1:导入大机的打卡文件,文件是一个文本文件,每行是一条记录,根据其中的联名编号找卡种,联名编号只有两种,8位编号或者8个0。如果没有找到卡种则报错退出。(联名编号是信用卡联名组织的一个编号,比如中石油卡,联名组织是中石油)
对卡种表加一个字段保存联名编号,默认值是8个0,然后一条sql解决问题:select * from cardtype where jointlyno = ?
上线后出问题了:运通卡文件无法导入。
调试跟踪后发现,运通卡的打卡文件的联名编号是8个空格,和以前的需求描述不一样,只好修改代码。
得到的需求是-- 需求2:如果是8个空格的肯定是运通卡
于是代码变成了先判断jointlyno是否是8个空格,如果是则直接返回全部的运通卡卡种,不是才是以前的那条sql
上线后又出问题了,有一个文件导入报错,没有说明什么卡等具体细节。
只好把那个文件拿过来调试跟踪,发现是有两个卡种比较怪异,他们的联名编号是10013xxx,3个x表示可以随意变化,因为这个是学生卡,3个x表示的是学校编号。问题就出现在这里,打卡文件里面的联名编号是确定的,比如是10013001,但是卡种表里面的却是10013xxx,所以按照那条sql 返回的记录是空。
看来只好继续改程序,变成了再加一个判断,如果联名编号前五位是10013的则不管后面3位是什么,判断前五位即可。即select * from cardtype where substr(jointlyno,1,5)= ? ,这个 ?是 jointlyNo.subString(0,5)。
这里出现一个 需求3:如果联名编号前五位是10013的则不管后面3位是什么,判断前五位即可

这么一个简单的问题为什么需要反反复复的修改呢?能否避免反复修改?如果无法避免,如果有效快速地应对这些修改?
这个案例很显然地原因就是客户对需求理解的不全面,以致于他自己在不断完善自己的需求,而代码也跟着需求在修改,这个修改是无法避免的,如果无法反抗,按照敏捷的做法那就拥抱变化吧,问题是怎么拥抱?我觉得需要用完备的测试来细化对需求的理解。
对于需求1,需要测试三种情况,1) 00000000 2) 正确的联名编号 3)错误的联名编号
8个空格就是第三种情况,10013001也是第三种情况。 但是这种情况都是在需求1中被客户声明说不会出现的情况,恰恰变化就出在这边。需求的变化是把几个错误的编号变成了正确的编号,这种完全相反的变化完全无法预料的。
需求2出现后 需要增加 一个 8个空格的测试,非8个空格的测试落入刚才3个测试中。
需求3出现后 需要增加  1)10013001的测试,2)10013888(假设10013888这个联名编号存在,而且对应的卡种不是学生卡) 3)10013999(10013999是一个不存在的联名编号)
如果第2、3两个测试的情况发生,那现在的代码就有bug。但是现在需求是10013开头的联名编号肯定对应的学生卡,这两个杞人忧天的测试需要吗?
很简单的一个问题,但是要写这么多的测试,每个case要写完备的测试真不是一件简单的事情,不知道有什么成套的测试写法。而且这些测试带来的作用仅仅是对需求的细化理解,并不能对代码的修改产生多大的帮助。这些测试如果用图来表达其实也不错,为何一定需要这么完备的单元测试代码呢?

猜你喜欢

转载自eyejava.iteye.com/blog/54410