有时我们会遇到生产中的错误,可以通过例如更改配置、禁用某些逻辑等来修复这些错误。
我和我的经理争论说我们应该在本地重现错误以确保修复工作,更重要的是,开发人员和 QA 可以将这些情况的检查作为常规发布的一部分。
我的经理认为这是浪费时间,因为该解决方案有效,因此无需在本地复制。
那么:我们是否应该尝试在本地重现以验证修复?如果您同意我的观点,关于如何将这一点推销给我的经理的任何指示?
如果您还没有重现该错误,那么您的“修复”只不过是猜测而已。
在我的头顶上:
如果在经济上可行(例如,不要为了重现环境而将某些用户的整个硬盘驱动器复制到您的本地计算机),我非常相信重现错误。
错误的不幸本质是通常只有一种方法可以修复错误,但有很多方法可以掩盖它,而且许多修复实际上是掩盖而不是修复。您可能永远找不到根本原因,因此该错误会再次出现,或者稍后会出现另一个看似不同的错误。
如果您能找到发生这种情况的示例(例如,来自同一根本原因的两个不相关的错误),您可能能够赢得您的老板的支持。
该错误的性质也存在疑问:
能否通过单元测试快速重现缺陷?如果是这样,从事修复工作的开发人员应该编写所述单元测试,将其集成到更完整的回归套件中。这确保了未来的工作不会重新引入该缺陷。
能否以编程方式重现缺陷(例如,使用 Perl 或 Python 脚本)?如果是这样,QA 团队可能应该有一个涵盖它的自动化测试用例,并且可以快速用于验证。
可以通过一组分步说明重现缺陷吗?如果是这样,QA 团队(或最初标记错误的人)应该提供绝对最少的重现步骤。
这三个原则极大地有助于推动我的测试团队的 QA 流程。
重现缺陷通常符合开发人员的最大利益。如果这是不可能的(例如硬件资源稀缺),那么直接与 QA(或最初标记该错误的人)合作将是下一个最佳选择。尽管有些缺陷很明显(例如菜单选项中的拼写错误),但其他缺陷可能会产生更大的后果,这可能会被知道应用程序底层状态的开发人员发现。
让开发人员重现缺陷以确认它们确实是缺陷也很有帮助。测试人员虽然不可或缺(作为软件测试人员;)),但通常缺乏对应用程序代码的深入了解,并且可能对为什么行为不符合他们的期望(或规范)没有深入的了解。
您不应该在本地复制它的唯一情况是不可行的情况。也许它需要大量数据、专有数据、硬件,或者它可能需要比您拥有的更复杂的设置。
我不得不这样做几次,因为我们无法在内部复制设置。(一些开发工作甚至已经在客户的系统上完成。)客户从一开始就知道他们超出了我们可以重现的范围,并且由此引发的错误将是一个痛苦的处理。
测试驱动开发背后的基本原则是你有一个展示一些特性的测试。
在这种情况下,您将创建一个演示该错误的测试。测试失败。
你修复错误。测试通过。和所有其他测试一样。您实际上已经修复了该错误而没有产生其他问题。
这个问题有很多很好的答案,但大多数都没有直接谈论经济情况,这可能是影响你经理的主要因素。
如果你不复制,那么你
在降低风险的努力之间权衡取舍很大程度上取决于具体情况——你正在生产什么样的软件,有多少客户,生产中的“坏”错误有多少(例如,销售网站是否出现故障,你会失败)每天一百万美元,或者网络论坛是否关闭,人们必须等到明天才能在线聊天),你有多少测试自动化(影响重现/回归错误的努力),......
许多(大多数?)经理都规避风险,因此在说服方面,请尝试说明各种风险(回归其他功能,部署实际上无法修复它的修复程序(并且在客户看来很愚蠢),... ) 以及估计您为减轻该风险所需付出的努力(复制成本和对修复有信心)。
你很急吗?如果是这样,那么重现错误!这会产生一种有条不紊的心态,您需要防止进一步的问题。你怎么可能发现旧的错误被重新引入?重现错误会引起其他人的注意:
好经理:“你在做什么?”
优秀的开发人员:“我们又遇到了那个错误。我正在重建测试环境,以便我们可以重放它。”
好经理:“WTF?我以为戴夫说他修复了那个?嘿戴夫,你没有修复那个错误吗?为什么我们又在这个问题上浪费时间?
相对:
混蛋经理:“你在做什么?”
优秀的开发人员:“我们又遇到了那个错误。我正在重建测试环境,以便我们可以重放它。”
混蛋经理:“不——我们没有时间。把它修好然后回滚。你有没有回复关于会议的电子邮件?我得走了——我得和史蒂夫一起 10 天。好。啊,把它回滚,然后发送那封电子邮件。”
作为导演,我告诉我所有的团队“今天花点时间”把事情做好,这样我们就不会半夜起床了。
不久前我读了一本关于调试的好书,它不仅建议重现错误,而且在修复它之后:
原因是你可能会为了修复一个错误而费尽心思,这将帮助你知道你已经修复了它。如果您不知道已修复它,它可能仍然会损坏。
(前几天我遇到了这样一个案例,其中一行似乎没有关系的代码导致我们的网站运行异常:当我取出这行代码时,网站可以正常工作,但是当我把它放入, 该站点还可以。但事实证明这只是巧合;无论我做什么,该站点每隔一段时间就会出错,因为它巧妙地让我登录和退出。您必须知道您的修复是真实的使固定。)
编辑: 我在一个老板对声称已修复但没有修复的错误非常暴躁的地方工作。发生这种情况是因为即使我(或其他开发人员)能够重现该错误,但我并没有以与测试人员生成它的方式完全相同的方式重现它。您不仅应该重现该错误,而且您应该确保您重现该错误的方式与测试人员完全相同。
(但如果您想先自己尝试,请继续;也许您会发现另一个错误!之后,让测试人员在您开始处理错误之前演示他/她的再现。)
您必须始终尝试。您需要确定它是错误、错误还是缺陷。您如何在不了解问题的情况下解决或缓解问题?
记录或测试套件将如何解决?状态是否合适
——“已修复”、“开放”、“无法复制”、“不会修复”、“功能”?
如果你不能重现它,仍然必须做出决定,让它飘入 /dev/null 就是要求它回来咬你。
必须在本地重现错误的最重要原因是确保在修复它时没有搞砸其他任何东西。如果修复只是一个配置或任何不需要重新编译的东西,那么这个参数就没有那么强大了,因为任何已经编译的东西都应该已经过测试。
如果你的经理没有明白这一点,那么除了向他展示修复错误实际上搞砸了某些事情的真实案例之外,你无能为力说服他,这会导致比在本地重现错误所花费的更多延迟.
我认为这个问题的答案取决于你如何测试你的错误。
除非上述问题的答案是肯定的,否则合并检查以验证错误修复已经发生将是乏味和痛苦的。也很难说服经理花时间来合并这些检查,因为他们总是会说“好吧,我们没有足够的人力资源来做这件事”
如果您在自动化解决方案上投入了一些时间,那么将这些测试添加到构建过程中将是不费吹灰之力,因为解决任何错误的第一步应该是创建一个无论如何在本地重现问题的测试。
对于我的项目,我们使用 subversion 进行源代码控制,使用 Jira 进行活动管理,使用 Hudson 进行构建,使用 Fitnesse 和 MSTest 进行测试。所有这些都使用持续集成捆绑在一起。Fitnesse 进行验收测试,MSTest 进行单元测试,每次执行构建时它们都会自动运行,从而为我们提供构建“好”程度的量化指标。
我发现不复制错误来修复它的想法很奇怪。
毕竟,在您重现问题之前,您无法确定问题是否存在。在那之前,它只是推测(即使消息灵通,它仍然是推测)。
现在,无论您是否进行单元测试,我认为与此讨论无关,因为可重复性只是您是否找到错误的问题?如果您正在测试错误的东西,进行一些不正确的假设,或者只是误解了(可能是模糊的)关于实际发生的错误报告,那么单元测试将无济于事。
这就是你重现问题的原因。
虽然说单元测试是解决方案,如果使用它们听起来不错,您不必重现错误,但我认为它在现实世界中行不通。他们没有在现场复制错误的事实意味着复制可能不是微不足道的。这可能意味着来源很复杂。如果问题在单元测试中表现得微不足道,那么该单元测试将是错误的再现。如果他们没有复制它,他们可能无法为它编写一个简单的单元测试。
如果你没有重现这个错误,你就没有真正理解它。您可能在系统中发现了一个错误,但这并不能保证您已经找到了客户所看到的错误。
如果你不能重现这个错误,你就不能确定它是否真的被修复了。您可能只处理问题的症状,而不是核心问题。客户可能对同一个核心问题有不同的向量,他们的问题不会得到解决。
是的,在可能/可行的情况下;见回归测试
在大多数情况下,您无法知道您重现的错误与您的客户遇到的错误相同。因此,复制并不能保证问题真的得到解决。
例如,客户在我参与的项目中遇到了通信错误。我们搜索了代码以修复任何可能的错误。一个错误涉及 PIC 微处理器中的 ASIC 错误,芯片勘误表提供了我们实施的解决方法。然后我的一位同事采取了极端措施来重现该错误,以便他可以声称我们客户的问题可能已经修复。
不是。
最后,我们添加了很多防御性编码,客户再也没有遇到过这个问题。我们不确定究竟是哪个修复解决了这个问题,知道并重现我们的客户遇到的问题会很棒,但归根结底,这些都不重要。重要的是软件的工作原理。
因此,能够重现错误并深入了解导致问题的原因固然很棒,但重现错误并不能保证解决客户的问题,工作软件更重要。
听起来您的工作场所在“无复制”范围内太过分了,当一点额外的工作可以生产出更可靠的软件时,这是一种耻辱。在这篇文章中,我认为光谱的另一端也不是那么好,所以我会尝试推动介于两者之间的东西。
我与我的经理争论说我们应该在本地重现错误以确保修复工作,更重要的是,开发人员和 QA 可以将这些情况的检查作为常规发布的一部分。
我特别同意关于开发人员和 QA 的部分,包括检查。这是日本人所说的Jidoka的一部分(代表“人性化的自动化”):
[...] 自动化可防止生产有缺陷的产品,消除生产过剩,并将注意力集中在了解问题并确保其不再发生。这是一个应用以下四个原则的质量控制过程:
- 检测异常。
- 停止。
- 修复或纠正眼前的状况。
- 调查根本原因并安装对策。
对策是防止再次发生。这就是您构建防错流程的方式(并且让缺陷发生的流程是有缺陷的流程)。好的管理者应该明白这一点。
更改配置、禁用部分逻辑等在生产环境中是一种临时解决方案。
我们需要通过本地测试来确保产品可靠并满足客户要求,跨设备(移动设备、平板电脑等)和跨平台(Firefox、Chrome、Internet Explorer)测试在这里也起着重要作用。
检查问题是先在本地复制,以确保产品的质量,因为如果客户发现同样的问题,那就是问题:)
提供可靠、无错误的产品理解和重现问题是最重要的。
正如您所提到的,通过更改配置、禁用某些逻辑等,可以修复错误(即无法重现)。但是如果客户有相同的配置,而你暂时要更改,那这实际上是一个大问题,所以跨设备(手机、平板电脑等)和跨平台(Firefox、Chrome、Internet Explorer)测试非常重要的。
试着让你的经理因为愚蠢而被解雇并得到他的工作,这可能是一个机会!
对于现场随机崩溃,有时您无法重现它们。我使用 Microsoft 的 Windows 错误报告服务收集的事后崩溃转储调试了罕见的竞争条件和“不可能的”崩溃。我认为微软大师 Raymond Chen 称之为“心理调试”。
如果您的公司向公众提供 Windows 软件(C++ 或 .NET),我强烈建议使用 Microsoft 的 Windows 错误报告 (WER) 服务。它是免费的,即使对于商业软件公司也是如此。它比编写自己的错误报告和故障转储收集服务更简单。WER 甚至会整理所有堆栈跟踪,以便您知道哪些崩溃是重复的,这在您不想调试数千个重复崩溃时很有帮助。:)
可能会重复已经写过的内容,但是是的!理由是:只发现一次错误。如果您可以编写一个复制错误的测试,您将不必再次手动测试它 - 您的自动化测试会找到它。
因此,您修复了该错误,并且您可以放心,您的软件将永远不会再遭受此错误的影响。这很好。这将节省您的时间。它会帮你省钱。