现代软件工程讲义 9 测试 关于闰年的测试(2)

发表于:2012-01-05来源:博客园作者:SoftwareTeacher点击数: 标签:软件测试
被 100 整除, 同时被400 整除的年份 被 4 整除, 但是不被100 整除的年份 被 4 整除, 同时被100 整除的年份 偶数, 不被4 整除的年份 奇数年份 其它非法输入的年

  被 100 整除, 同时被400 整除的年份

  被 4 整除, 但是不被100 整除的年份

  被 4 整除, 同时被100 整除的年份

  偶数, 不被4 整除的年份

  奇数年份

  其它非法输入的年份

  程序员都知道程序经常在边界条件附近出错, 针对IsLeapYear(), 你可以得出下面两个测试用例:

  设计允许的最小的年份

  设计允许的最大的年份

  啊, 设计中没有考虑这个? 那这个设计要出现问题。 在1950-70 年代, 很多程序用两位数字表示年份 (00 – 99), 那些聪明的程序员认为这已经足够了, 没想到这些程序和设计影响了很多要和它们兼容的程序 (就像 Excel 要兼容 Lotus 1-2-3 那样), 到了1990年代后期, IT 业花了很多人力物力来解决 Y2K 的千年虫问题。 一些程序员非常钟爱的 UNIX 操作系统 (32 位) 也有自己的千年虫问题, 它会发生在 2038 年! 到时候人们还会用32位的机器么? 也许在一个大家想不到的关键部位, 一些老旧的, 嵌入式的 Unix 系统会悄悄地发作…

  除了从外部的输入/输出来设计测试用例, 我们也可以从内部考虑, 看看这些测试用例是否把所有语句都覆盖了。 但是要注意, 即使所有语句都被测试用例覆盖了, 程序还是可能出错!

  例如, 我们测试 NumberToYear(), 分析它的各个条件, 我们推算出我们的数据要覆盖下面一些情况:

  输入的 day 大于 365

  输入的 day 小于 365

  输入的 day 大于 366 并且1980 年到那一年中, 至少有一年是闰年, 例如输入一个2008年的某一天。

  输入的 day 大于 366 并且1980 年到那一年中不包括闰年。

  这样是不是就把所有路径都包括了? 程序就没有错了?

  不巧的是, 这个程序用在了某著名公司的产品上, 出品的前两年没什么事, 到了2008 年的最后一天 (那一年有366 天), 出了一个问题:

  年份一直增加到了 2008, 这时候, day == 366, 我们看看循环能做下去么?

  if (IsLeapYear(year))

  {

  if (days > 366) //day == 366, 不满足条件

  {

  days -= 366;

  year ++;

  }

  所以 day 没有减少, year 也没有增加, 循环又继续下去, 任何条件都没有改变, 进入了死循环!

  不幸的是, 这个程序经过了种种测试, 进入了市场. 于是, 在2008 年的最后一天, 许多用户发现他们的 Zune Player (只限于 Zune 30 型号) 开机之后就进入死锁状态…

  http://www.usatoday.com/tech/products/2008-12-31-zune-mystery_N.htm

  http://www.zuneboards.com/forums/showthread.php?t=38143

官方的说法是 - 大家等到明天就好了!
Smile
不用说这对于用户, 对于产品的口碑, 对于这个代码的开发者, 测试者是一个极大的打击!

  如果你是一个测试人员, 你应该增加什么测试用例呢? 如果用边界条件分析, 应该有至少 4 个新的测试用例:

  闰年的第一天;

  闰年的最后一天;

  平年的第一天;

  平年的最后一天

  对于程序员, TA 应该如何修改代码?

  错误之三: 没想到还有闰年

  在IT 行业混了很多年的好处之一就是你可以看到不少 bug. 下面又来了一个:

  Windows Home Server与客户端connector第一次连接时,需要Server为connector颁发安全证书。出于某种实现上无法避免的原因,客户端的证书日期一定要早于Windows Home Server,否则生成证书的函数会fail。Windows Home Server是2007年7月RTM的。为了方便起见,设计中规定,给客户端生成证书的函数使用2006年作为年份。

  <完整的故事 link: http://yishan.cc/blogs/lilei105/archive/2008/03/03/885.aspx>

  作为一个程序员, 你如何实现这个设计呢? 一拍脑袋, 就取当天的日期, 然后把日期中的年字段改成 2006, 不就行了么?

  然后到了 2008/2/29 这一天… 程序把日期改成了 2006/2/29. 然后就悲剧了.

  软件团队在自问: 为啥我们当初没测出来? 如果你是测试人员, 你会想到这个测试用例么?

原文转自:http://www.ltesting.net