2008年12月13日星期六

利用mercurial bisect 二分查找bug

前几天QA找到了一个严重的bug,我们编写了一个测试,并修复了它。 问题是我们在哪个版本引入了这个bug? 在1.0版本的时候,这个功能还是正常工作的,

从1.0版本到现在我们进行了上千次提交,找到引入问题的那个版本,看起来是"不可能"的任务,但是因为mercurial提供了bisect,而变的非常容易。

bisect是一个利用二分法来查找在哪个版本中引入bug的一种方法。大致的思路是先标记一个已知没有bug的版本为"good", 再标记一个已知有bug的版本为"bad", 然后hg会自动将版本更新到这两个版本的中间,然后开发者通过运行测试(自动或者手工)决定标记这个版本是"good"或者"bad", hg会再次决定一个中间版本让我们进行测试,直至找到一个相邻的good版本和bad版本,这个bad版本就是我们引入bug的版本。

举个例子:

假如版本1是没有bug的版本,版本10是有bug的版本,我们是在版本7引入了这样一个bug。hg寻找它的办法是:


hg bisect init (初始化数据库)
hg bisect bad R10 (标记版本10是有bug的版本)
hg bisect good R1 (标记版本1是没有bug的版本)


然后,hg会自动更新到R1-R10的中间版本R5,通过运行测试,我们知道这是一个没有bug的版本,于是标记这个版本是没有bug的
hg bisect good


接着,hg自动更新到版本R5-R10的中间版本R8,通过运行测试,我们知道这是一个有bug的版本,于是标记这个版本为bad
hg bisect bad


接着,hg自动更新到版本R5-R8的中间版本R6,通过运行测试,我们知道这是一个没有bug的版本,标记这个版本为good
hg bisect good


hg自动更新到版本R6-R8的中间版本R7,通过运行测试,我们知道这是一个有bug的版本,标记这个版本
hg bisect bad


这样,最后hg通过2分法不断缩小范围,我们得到了这样一个结果

R7 bad
R6 good


这样我们可以得知在R7引入了bug,再分析R7所提交的文件就可以明白当时的错误在哪里了。

这样通过自动化测试和mercurial提供的二分查找,我们可以轻松的找到错误的根源。

没有评论: