在我看来,如果最终用户在生产中发现了严重的错误,应该添加一个失败的单元测试来覆盖该错误,从而有意破坏该构建,直到修复该错误为止。我这样做的理由是构建应该一直失败,但这并不是由于自动测试覆盖率不足所致。
我的几个同事不同意说不应该检查失败的单元测试。就正常的TDD惯例而言,我同意这种观点,但是我认为应该以不同的方式处理生产错误-毕竟,为什么要允许建立已知缺陷的成功方案?
是否有其他人具有处理这种情况的可靠策略?我知道故意破坏构建可能会对其他团队成员造成破坏,但这完全取决于您使用分支机构的方式。
在我看来,如果最终用户在生产中发现了严重的错误,应该添加一个失败的单元测试来覆盖该错误,从而有意破坏该构建,直到修复该错误为止。我这样做的理由是构建应该一直失败,但这并不是由于自动测试覆盖率不足所致。
我的几个同事不同意说不应该检查失败的单元测试。就正常的TDD惯例而言,我同意这种观点,但是我认为应该以不同的方式处理生产错误-毕竟,为什么要允许建立已知缺陷的成功方案?
是否有其他人具有处理这种情况的可靠策略?我知道故意破坏构建可能会对其他团队成员造成破坏,但这完全取决于您使用分支机构的方式。
Answers:
我们的策略是:
签入失败的测试,但用进行注释@Ignore("fails because of Bug #1234")。
这样,就可以进行测试,但是构建不会中断。
当然,您会在错误数据库中注意到被忽略的测试,因此,在修复@Ignore测试后将其删除。这也可以作为错误修复的简便检查。
在失败的测试中破坏构建的意义并不是要以某种方式使团队承受压力,而是要提醒他们出现问题。一旦发现问题并将其提交到Bug DB中,就没有必要为每个构建都运行测试了-您知道它将失败。
当然,该错误仍应修复。但是安排修复时间是业务决策,因此并不是开发人员真正关心的问题……对我而言,一旦将错误提交到错误数据库中,就不再是我的问题,直到客户/产品所有者告诉我他们希望对其进行修复。
您为什么要允许构建成功解决已知缺陷?
因为有时您有时间限制。或者该错误太小,以至于真的不值得将产品的交货时间推迟几天进行单元测试和修复。
另外,每次发现错误时有意破坏构建的意义何在?如果找到了它,请对其进行修复(或将其分配给要修复的人员),而不会打扰您的整个团队。如果您想记住要修复的错误,则需要在错误跟踪系统中将其标记为非常重要。
有测试可以确保您不会(重新)引入问题。失败的测试列表不能替代错误跟踪系统。POV中有一些有效性,即失败的测试不仅表示错误,而且还表示开发过程失败(从粗心到识别不良的依存关系)。
“中止构建”是指阻止构建成功完成。测试失败不会那么做。这表明该版本具有已知的缺陷,这是完全正确的。
大多数构建服务器会随着时间的推移跟踪测试的状态,并且会为自添加以来一直失败的测试分配不同的分类,而不是将其归类为回归(过去通过但不再执行的测试),并且还会检测修订的版本。发生了回归。
我认为应该添加失败的测试,但不能明确地将其添加为“失败的测试”。
正如@BenVoigt在他的答案中指出的那样,失败的测试并不一定会“破坏构建”。我猜每个团队的术语可能会有所不同,但是代码仍然可以编译,并且产品仍可以通过失败的测试交付。
在这种情况下,您应该问自己,
测试意味着要完成什么?
如果存在测试只是为了让每个人都对代码感到满意,那么添加一个失败的测试只是让每个人都对代码感到不满意,似乎效率不高。但是,首先测试的效率如何?
我的断言是,测试应该反映业务需求。因此,如果发现“错误”表示未正确满足要求,则也表明测试未正确或完全反映业务要求。
那是要首先修复的错误。您不是在“添加失败的测试”。您正在更正测试以更准确地反映业务需求。如果代码随后未能通过这些测试,那是一件好事。这意味着测试正在发挥作用。
修改代码的优先级由企业确定。但是在确定测试之前,可以确定该优先级吗?为了使他们能够优先做出决定,企业应该了解确切的故障,故障的原因以及故障的原因。测试应表明这一点。
进行不完全通过的测试并不是一件坏事。它会产生大量已知问题,需要对其进行优先级排序和相应处理。但是,拥有无法完全测试的测试是一个问题。它质疑测试本身的价值。
换句话说,构建已被破坏。您要做的只是确定是否要引起注意。
在我们的测试自动化团队中,我们检入失败的测试,只要它们是由于产品缺陷而不是由于测试缺陷而失败。这样我们可以为开发团队证明,嘿,他们打破了它。破坏构建的做法很不容易,但这与检查可完全编译但失败的测试并不相同。
编写一个您知道在修复该错误之前将失败的测试是一个好主意,这是TDD的基础。
破坏构建是一个坏主意。为什么?因为这意味着在修复之前,任何事情都无法继续进行。它实质上阻碍了开发的所有其他方面。
示例1
如果您的应用程序很大且有很多组件,该怎么办?如果其他团队以自己的发布周期来处理这些组件,该怎么办?强硬!他们必须等待您的错误修复!
示例2
如果第一个错误很难修复,而您发现另一个优先级更高的错误怎么办?您还会破坏第二个错误的构建吗?现在,您必须先修复两者,然后才能构建。您已经创建了人为的依赖项。
没有逻辑上的原因导致测试失败会停止构建。这是开发团队需要做出的决定(可能需要管理层讨论),权衡发布具有已知错误的构建的利弊。这在软件开发中很常见,几乎所有主要软件都发布时至少带有一些已知问题。
这取决于测试应该扮演的角色以及测试结果如何影响所采用的构建系统/过程。我对破坏构建的理解与Ben的理解相同,同时,我们不应该有意识地检入破坏现有测试的代码。如果这些测试“晚些”进行,则忽略它们只是为了减少不必要的破坏性,这可能是“好的”,但是我发现这种忽略测试失败(以便它们似乎通过)的做法相当令人不安(尤其是这样)对于单元测试),除非有一种方法可以将测试指示为红色或绿色。
当然,这取决于错误,但是通常,如果在手动或自动测试过程中未发现错误,则表明您的研究范围存在差距。我绝对会鼓励找出根本原因,并在问题之上打个单元测试用例。
如果计划在维护部门中进行热修复是生产问题,则还需要确保该修复程序可以在主线上运行,并且开发人员不能通过过度狂热的合并冲突解决方案错误地销毁该修复程序。 。
此外,根据您的发布策略,是否存在新近更新的单元测试可以帮助确认开发人员确实已解决了问题,而不仅仅是更改了问题((问题还是测试?),尽管这取决于对代码进行编码。在新的单元测试中正确的要求。
向构建中添加“知道失败”测试的一个问题是,您的团队可能会养成忽略失败测试的习惯,因为他们期望构建会失败。这取决于您的构建系统,但是如果失败的测试并不总是意味着“某些东西刚刚坏了”,那么就很容易对失败的测试给予较少的关注。
您不想帮助您的团队进入这种思维方式。
因此,我同意sleske的意见,您应该添加测试,但出于自动构建的目的,请将其标记为“忽略”,直到修复该错误为止。
另一个选择是将失败的测试检查到源代码管理系统中的单独分支中。根据您的实践,这是否可行。有时,我们会为正在进行的工作打开一个新分支,例如修复一个不重要的错误。