差不多是我开始做测试的第二年,我碰到了一个至今还没有忘记的BUG,印象中差不多也是我经手的最严重的BUG。
———————————————惨案分割线—————————————————
我们当时在做外汇交易订单管理系统,里面有个模块是账户管理,理所当然“删除账号”是一个常规功能。那个版本其实做的很“顺利”,我们如期提交了代码,并按常规方式在某个周五让系统上了线。
很不幸的是,上线后一周的某个晚上,项目组就接到了“投诉”,有用户登不上系统了,他们可是正常有效的用户啊。我们美国的架构师应该是当地时间天没亮就被电话叫起来修复问题。于是,第二天的电话会议上,我们被告知生产环境上整个账户表的数据都被清空了。幸好有备份数据,不然这个篓子就捅大了;所有会议现场的人员都惊出一身冷汗。
马上,开发团队开始分析代码,也很快找到了问题所在:我们的开发在写SQL语句的时候,漏写了一个括号,导致判断语句中原本应该是“并”的条件被解析成“或”,于是整个删除操作几乎变成了在一个永真的前提下执行。换言之,只要有人触发了删除任何一个账号的操作,差不多整个账户表格的数据都会被清掉。至于为什么会有这个问题,倒不仅仅是“偷懒”或者“疏忽”这么简单,而是我们当年在学校里学习SQL的时候大都基于SQLServer体系,它对于SQL的解析与Oracle是有一定偏差的。正是因为这个偏差,导致了我们的开发自信地认为加括号是多此一举啊。
切换回QA这边,我们的测试小朋友为什么就漏过了这么严重的问题呢? 复盘一下,我们的测试用例的验证点大概是这么写的:“删除后,页面查询该账户,提示不存在;同时用SQL语句直接去数据库查询该账户,返回空结果。”很显然,整个账户表都被删除之后,作为其中指定删除的“账户”也是不存在的了,那么这个验证点无疑是通过的啊。于是,这个BUG躲过了单元测试和功能测试。从这个角度看,我们的测试人员并没有特别严重的过错;而更多是我们整体测试策略的不完善和个人经验的不足。
单就这个场景本身,我们QA小组经过了几番讨论,定了一个新规:
所有的删除操作,不仅仅验证是否有效删除、同时要检查是否过度删除。
如何判定是否过度删除,我们想了一招:用删除操作前和删除操作后的数据库存储条目做对比,从量的变化上做判断。
这个问题很快也就过去了,而它引出的测试范围外延的思考,则至今还在我的脑海中盘旋~~