Bug跟踪

Bug跟踪是一个宽泛的话题;贯穿本书会讨论此问题的各个方面。尽管这里我们要着重于配置和技术因素,但是首先要从一个策略问题开始:Bug跟踪系统中应该包含哪些信息?

术语Bug跟踪很有误导性。Bug跟踪系统也通常会用来跟踪哪些初始与结束状态不同,包含可选的中间状态,并在生命周期中积累信息的问题,例如新特性请求、一次性任务以及被动性的补丁。由于这些原因,Bug跟踪也被称为问题跟踪(issue trackers)缺陷跟踪(defect trackers)制品跟踪(artifact trackers)请求跟踪(request trackers)以及问题票跟踪(trouble ticket systems)Appendix B, 自由Bug跟踪系统包含了一个此类软件的列表。

在本书中,我会继续使用“Bug跟踪(bug tracker)”这个名称,因为大多数人这样称呼,但我会使用问题(issue)来称呼Bug跟踪数据库中的单个条目。这让我们可以把用户遇到的(Bug本身)正常或不良行为与跟踪系统中Bug的发现、诊断和最终解决的记录区分开来。请牢记,尽管大多数问题与实际的Bug相关,我们也可以用其来跟踪其它类型的任务。

典型的问题生命周期如下:

  1. 某人发起了一个问题。他提供了摘要,初始描述(如果合适则包含重现方法;如何激励好的Bug报告请看Chapter 8, 管理志愿者the section called “将每个用户当作潜在的志愿者”),以及其它跟踪系统要求的信息。项目可能对发起人一无所知—Bug报告和特性请求既可能来自用户社区,也可能来自开发者。

    一旦发起,这个问题就进入了打开(open)状态。因为还没有作出任何行动,一些跟踪系统也将其标示为未验证(unverified)未开始(unstarted)。它还没有分配给任何人;或者在某些系统中将起分配给一个冒牌用户来表示其还没有真正的分配。此刻,它存在于一个保留区:这个问题已经记录,但是还没有成为项目关注的一部分。

  2. 其他人读到这个问题,并做出回复,或许会再向发起者询问来澄清一些问题。

  3. Bug得到重现(reproduced)。这可能是其生命周期中最重要的一个时刻。尽管bug还没有修正,但发起者之外的人重现这个事实可以证明这个bug的真实性,此外,可以确认原发起者通过报告真实的bug为项目做出了贡献。

  4. Bug得到诊断(diagnosed):它的原因得到确认,如果可能,会对修正这个bug所需的工作量做出评估。请确认这些内容会在问题中得到记录;如果诊断人要离开项目一会儿(对于志愿开发者这很普遍),其他人应该能够接手。

    在本阶段,或者前一个阶段,开发者可以“获取”问题所有权并将其分配(assign)给自己(Chapter 8, 管理志愿者the section called “明确区分调查和指派”详细描述了分配过程的细节)。问题优先级(priority)也可以在本阶段设置。例如,如果某个问题严重到足以影响下一个版本的及时发布,则需要尽早标示出来,跟踪系统必须能够使其突出显示。

  5. 问题纳入解决的日程(schedule)。纳入日程并不是意味着规定一个解决的日期。有时候只是决定未来的那个版本(下一个版本不是必须的)必须解决这个bug,或者这个bug将会阻碍哪些特定版本。如果很容易修正,也可以取消纳入日程这一步。

  6. Bug得到修正(任务完成、或应用了补丁、或者其他类似的事情)。变更或者变更集必须记录在问题的回复中,其后是问题被标注为解决(resolved)而得到关闭(closed)

这个生命周期有许多变种。有时候一个问题再发起之后很快就会关闭,例如发现它不是一个bug,而只是部分用户的误解。随着项目获得了越来越多的用户,就会带来更多无效的问题,开发者会用日益缺乏耐心的回应来关闭这些问题。要尝试预防这后一种趋势。这对谁都没有好处,每个案例中的每个单独用户对于此前的无效问题没有任何责任;统计学的趋势只是从开发者而不是用户的视点有效。 (在本章后的the section called “Bug跟踪的预过滤”将会看到减少这种无效问题的技巧。)另外,如果不同的用户反复经历同样的误解,这或许意味着软件的某方面需要重新设计。如果有一个问题经理监视着bug数据库,就会很容易发现这种模式;见Chapter 8, 管理志愿者the section called “问题管理员”

生命周期的另一种常见变种是问题在步骤1之后直接以重复(duplicate)状态关闭,重复是某人发起了一个项目已知的问题。重复不仅限于开放的问题:它也可能来自已经修正的bug重现(这个称为衰退(regression)),无论何种情况最佳的解决方式是重新打开最初的问题,并将新的报告复制到最初的问题中。Bug跟踪系统应当能够双向保持联系,这样重复的重现信息中就可以在原问题中看到,反之亦然。

开发者关闭这个问题的第三种情况是他们认为已经修正了问题,只是让原报告者拒绝这个修正并重新打开它。这通常仅仅是因为开发者不能访问重现bug的环境,或者因为他们不能通过报告者的再现描述测试这个修正。

除了这些情况,不同的跟踪软件也有一些其它小的生命周期细节。但基本的生命周期是相同的,生命周期本身并不特定于开源软件,只是暗示了开源项目如何使用他们的bug跟踪系统。

就像步骤1暗示的,跟踪系统和邮件列表或网页一样,是项目的门面。任何人可以发起一个问题,任何人可以浏览当前打开的问题列表。由此我们也能推断我们无法知道有多少人在等待给定问题的进展。而开发社区的规模和技巧限制了问题解决的速率,项目至少应该知道每个出现的问题。即使问题会缓慢小时,一个回复也会鼓励报告者保持参与,因为她能感觉到有人已经为其所作的事情登记(请牢记填写一份问题远比发一封邮件更麻烦)。此外,一旦开发者看到一个问题,它就进入了项目的意识中,也就是开发者会查看此问题的类似情况,或者会与其他开发者讨论,等等。

及时反应的需求意味着两件事:

与邮件列表交互

请确保bug跟踪系统不会成为讨论论坛。尽管让人参与bug跟踪很重要,但从根本上它不适合实时讨论。更应该将其当作归档,组织证据和其他讨论(通常发生在邮件列表)的引用。

做出这种区别有两个原因。首先,Bug跟踪系统的使用比邮件列表(或者实时讨论论坛)更加笨拙。这不是因为bug跟踪系统都没有好的用户界面设计,而是因为它们的界面设计用来捕捉和展示分离的状态,而不是自由流动的讨论。第二,不是每个参与到特定问题讨论的人都必须注意bug跟踪系统。优良的问题管理(见Chapter 8, 管理志愿者the section called “像分担技术任务一样分担管理任务”)是让每个问题被恰当的人注意到,而不是让所有的开发者监视所有的问题。在Chapter 6, 交流the section called “Bug跟踪系统中无对话”,我们会关注确保人们不会脱离合适的论坛而陷入在bug跟踪系统内讨论的问题。

有一些bug跟踪系统可以监控邮件列表并自动记录关于已知问题的邮件。他们通常是通过在邮件列表中,将邮件标题出现的问题标示号码作为特殊字符串来识别问题;开发者学着在他们的邮件中包含这类字符串来触动跟踪系统的注意。Bug跟踪系统可以保存整个邮件,或(更好一点)只是记录邮件在邮件列表归档中的链接。无论何种方式,这是一个非常有用的特性;如果你的跟踪系统有这个功能,要确保在开启它的同时提醒人们利用这个特性。

Bug跟踪的预过滤

大多数问题数据库最终会遭遇相同的困境:由好心但没经验或消息不灵通用户所发起的重复和无效问题的洪流。与这种趋势斗争的第一步通常是在bug跟踪系统的前页放置一个显著的提醒,解释如何知道一个bug是否确实是bug、如何查找bug是否已经被发起、以及如果依然认为是新bug时如何有效的报告。

这会暂时减少噪音,但是当用户数增加后,问题还是会出现。每个单独的用户都不应该因此被谴责。即使他们的第一个bug报告没有用处,你还是要鼓励他们保持参与并在以后提出更好的问题。同时,项目需要保持问题数据库的垃圾越少越好。

这两件事可以最大程度的防止这些问题:请确认监视bug跟踪系统的人有足够的知识,能在问题无效或重复时关闭它,而且能够要求(或强烈的鼓励)用户在填入跟踪系统前确认他们的bug。

第一种技术看起来被广泛使用。即使项目有巨大的问题数据库(例如,Debian在http://bugs.debian.org/的bug跟踪系统,目前有315,929个问题)也是这样安排的,这样某人进入时就能看到所有的问题。不同的问题类别可能是不同的人。例如,Debian项目包含了一组软件包,这样Debian就能够自动路由每个问题到合适的包维护者。当然,用户有时会把问题类别搞错,这样一开始问题就会发送到错误的人,而他可以再将其转向到其他人。然而,最重要的事情是负担被分担了—无论用户在填写的时候是对是错,问题监视的任务还是会在开发者之间分配,所以每个问题都能够得到及时的回复。

第二种技术应用的没有那么广泛,可能因为它很难被自动化。本质思想是每个新问题都是经过伙伴处理后进入到的数据库中。当用户认为他发现了一个问题,他就会被要求在邮件列表或IRC频道中对其进行描述,然后得到某个人对其是bug确认。尽早引入第二双眼睛可以防止许多虚假的报告。有时候第二方可以识别出这个行为不是一个bug,或者已经在最近的发布中被修正。或者她可能由于类似症状bug而感到熟悉,而且可以通过给用户指明老的问题来防止重复的填写。通常仅仅是询问用户“你查找过bug跟踪系统以确定这个问题是否已经报告过了吗?”许多用户不会想到这个一点,如果有人期望,你可以愉快的为他们查找一下。

这种伙伴系统确实可以保证问题数据库的清洁,但是也有一些不利的地方。许多用户无论如何也要独立发起问题,对为发起新问题而寻找伙伴的指南看不到或者视而不见。因此,还是需要有志愿者关注问题数据库。此外,因为许多新报告者不理解维护问题数据库的难度,对他们忽略指南的行为进行过于严厉的斥责是不公平的。所以志愿者必须保持警觉,联系如何反弹未经搭档处理的问题给报告者。目标是训练每个报告者在未来使用伙伴系统,这样就有一个日益增长的能够理解问题过滤系统的用户池。当看到一个未经伙伴系统处理的问题时,理想的步骤是:

  1. 立刻回复问题,礼貌的感谢用户的填写,但是向他们指出伙伴系统的操作指南(当然应该在网站的显著位置)。

  2. 如果问题是明显有效而且没有重复,想办法证明它,使之开始正常的生命周期。毕竟,报告者没有被告知伙伴系统,所有浪费工作量关闭有效的问题是没有意义的。

  3. 否则,如果问题不是很清楚的有效,关闭它,但是要求报告者在得到伙伴的确认后重新打开它。当他们这样做时,他们应当放置一个确认邮件列表线索的引用(例如一个邮件列表归档的URL)。

请记住尽管系统会逐渐改善问题数据库的信/噪比,但是不会阻止误填的发生。完全防止误填的唯一方法是关闭bug跟踪系统,只开放给开发者—治愈几乎永远比疾病本身更坏。应当接受无效问题的清理是项目日常维护的一部分,并努力得到更多的人们来帮忙。

Chapter 8, 管理志愿者the section called “问题管理员”也有介绍。