最近,某著名信息安全公司发布了一个更新补丁,导致用户的密钥管理软件无法正常工作,应该从类似的问题中学习到怎样的教训呢?评论家Andrew Binstock撰文强调了回归测试的重要性!
有关问题的背景,Andrew做了相应的介绍:
在我看来,不使用一个全面的回归测试集合是错误的。这种错误将导致正如卡巴斯基——这家消费者导向的安全软件公司(提供反病毒,反恶意软件)——所面临的尴尬局面。卡巴斯基的一款产品是供用户存放安全密钥的密钥安全软件。当用户需要使用一个密钥时,用户通过密钥安全软件的密码打开软件,复制/粘贴要使用的密钥。其要使用的密钥会显示为一组圆点。完成操作后,他们关闭安全软件然后继续他们的工作。通过一个简单的列表,用户就可以添加新的密钥。这个列表还非常明智地添加了密钥有效期限。用户也可以将选择“从不设定有效期限”。
下面我将仔细说明。更新的结果是所以的密钥都突然过期,而且修改有效期的按钮失效。我并不知道卡巴斯基是怎么开发软件的。尽管如此,我们不难从这些现象推断出一些信息。
Andrew强调了测试的重要性:
和很多人一样,我一直以来很欣赏“Uncle Bob”Martin的部分观点。尽管我不赞同他的一些观点(有时是强烈不赞同),但我从来没有质疑过的他一直强调的这一点:没有测试的提交代码方式是不正确的。我并不是在推崇Martin的大解决方案(测试驱动开发),而是强调他基本立场的正确性。老实说,Martin即不是唯一的、也不是第一个提出测试与提交代码同步的重要性的人。Kent Beck、Michael Feathers等许多持续集成和DevOps的倡导者们,一直以来都持有这个观点。但是Martin孜孜不倦的倡导这个观点。并且正是由于他的推动努力,很多勤奋的开发人员今天本能地理解了写完代码后立即进行测试的重要性。
测试已经成为开发工作的重要部分。Andrew认为,以至于当开发者没有进行测试时,人们会认为开发者又陷入了老的工作模式或者指责开发者草率行事,对自己的代码毫不关心。直到几年前,我们还可以说可以不用对开发者编写的代码进行测试,就能成功地把人类送到月球上。当时,大部分人都认为自己可以不进行测试就完成出色的代码。直到今天,还都需要面对这个重要的问题:他们如何知道自己对代码的修改不会影响到现存代码的正常运行?测试的作用——作为整个代码的传感器和监视器——是对进行测试工作的必要性的最有力的论证。
对于该信息安全公司的问题,Andrew分析道:
卡巴斯基公司肯定没有进行回归测试,否则它将不会遇到这个问题。这个问题发生在Windows 7的机器上——我的朋友告诉我这个问题发生在普通的Window 7家庭机上(家庭机的主要运行的程序是Office、Outlook和IE浏览器)。评论说很多Window 7的电脑都遇到了这个问题。考虑到Windows 7是当下最流行的操作系统,卡巴斯基公司肯定没有针对这款系统进行测试。
还有另外一条线索说明测试工作没有进行或者至少进行的不充分:这款软件里被标明“从不设定有效期限”的密钥突然显示为过期状态,而且其到期日期变为1601年。
Andrew认为,这个日期非常麻烦。在测试中,了解程序的不变量十分有用。不变量是程序中不管程序处于什么状态,总为真的一些东西。不变量是程序中丰富的“静脉”,我们在回归测试集合中要充分利用它们。在这个程序中,我们可以知道它的一个不变量是任何软件的到期日期都不能早于软件发布日期。打个比方,如果说卡巴斯基是在2011年7月1日第一次发布的这个软件,那么所有用户的密钥的截止日期就不会早于这个日期。这就是一个不变量——任何密钥的截止日期不能早于2011年7月1日。如果密钥的截止日期早于这个日期,那就说明程序有错误。而现在程序中出现1601年这个日期,这说明测试工作不足或设计工作很差。也就是说,使用无效的日期作为使用的数据,如一个错误代码。这种重用数据字段来代表一个完全陌生的数据项的做法是很可怕的。这种做法在磁盘空间和内存都很昂贵的时代非常流行。标志位的字节常常被重载来表示独特的信号或者罕见的条件。如今在资源受限制的嵌入式系统中我们依旧可以见到这种做法,那是因为现在还没有更好的做法来替代这种做法。不过对于桌面程序,这是一个严重的问题。首先,你会给正在试图解决一些困惑问题的用户带来新的令人困惑。其实,你会让不变量不稳定。现在,针对不变量的测试必须测试所有合法的异常值——一个常数的维护问题作为新的误差值被添加到这个重载的字段。相反,错误常常被他们自身的领域和诊断所标明。这保证了测试的完整性,代码的清晰、可读性。关于后者,想想那些测试错日期、翻译错日期的代码。当你在你是用的应用程序中看到这些问题是你会怎么想?
我朋友现在明智的思考她是否应该更换一款安全软件,用一款从不会锁住她的密钥的软件。如果你不充分测试你的软件(从开发者测试开始进行——开发者测试将在产品发布前早早发现问题),你可能会遇到大麻烦。