破旧/旧版单元测试


13

我在一家大公司工作,负责一个带有数千个junit测试的大型Java应用程序。自从我担任这个职位以来,已经有200到300个失败的测试(可能是多年失败的测试)。这些测试既旧又脆弱,并且杂乱无章,通常以实时沙盒数据结尾。

我的目标是100%通过测试,这样我们就可以打破单元测试失败的基础,但是直到解决了失败的测试之后我才能做到。我的预算很少,因为维护预算主要用于支持,但是我的团队已经确定并修复了低挂的水果测试(主要是配置/本地资源问题),而我们的测试只有30-40个非常丑陋。

对最佳实践有何看法?我认为测试不是有价值的,但是我也不知道他们正在测试什么,或者为什么他们不钻研就无法工作,这需要我们花费很多时间和金钱。

我想我们应该用我们知道的任何东西记录破损测试的状态,然后完全删除或忽略破损测试,并输入一个较低优先级的错误/工作项来调查和修复它们。然后,我们将达到100%的水平,并开始从其他测试中获得真正的价值,如果我们有维护/重构的意外之财,我们将能够再次进行选择。

最好的方法是什么?

编辑:我认为这是一个不同于该问题的问题,因为我对我们应该编写的测试有明确的方向,但是我继承了遗留失败的测试,以便在当前的大量测试变得有意义之前解决这些问题。


1
绝对同意您应该摆脱30-40个丑陋的测试。但是,“如果我们有维护/重构的意外之财,我们将能够再次将它们捡起来”听起来像是一厢情愿。我不确定将它们记录为低优先级项目是否有任何真正的好处,因为此类项目具有从不采取行动的习惯。
David Arno

1
我建议您阅读本书:有效地使用旧版代码。推荐书并不能解决您的问题,但是您会在其中找到许多有关单元测试的好建议。

4
这可能是某些东西的重复,但这不是问题。这不是在问如何避免编写易碎的单元测试,而是在如何管理失败的已编写单元测试的继承代码库。

1
似乎您已经找到了解决方案。
布朗

2
@gnat我不同意。从个人经验来看,“昨晚某个东西破坏了我的许多单元测试”和“我继承了很多旧代码,并且单元测试失败了很长时间,没人知道为什么”之间有很大的区别。一个是当前开发的问题,一个是旧版软件的问题。这里需要两种不同的方法。链接问题的最高答案未解决遗留问题。

Answers:


17

我要做的是首先禁用失败且始终失败的测试。

使其测试失败很重要。

当您进行调查时,您也许可以向在公司工作了较长时间的人询问有关他们的信息,也许有很多关于他们的部族知识可以记录/捕获。也许从您的VCS日志中。“哦,自从我们升级到X以来,该测试始终失败”,否则其他信息可能会有用。

一旦知道要测试的功能是什么,就可以确定:

  • 我们是否在乎这个测试
  • 测试这个有多重要

然后制作一个优先级列表。

此列表上可能没有任何东西足够重要,因此以后再花更多时间,因为已经被忽略了很多年。因此,我不会花太多时间/资源来记录和分析所有这些损坏的测试。


1
我喜欢预先禁用测试的想法,但保守的环境可能更喜欢较小的增量移动。我想这取决于您的公司吗?
亚伦·霍尔

1
@AaronHall-我认为,如果您着眼于眼前的代码更改需求(修复和增强功能)并确定与之相关的任何损坏的测试,则可以将所有这些功能打开,评估和修复测试,并在了解以下情况的基础上进行代码更改测试可以通过,得到修复或被删除。
JeffO'1

6

我将执行以下操作:

  1. 尝试确切确定失败的测试试图验证的内容。

  2. 分流-如果某些测试试图测试不重要的事物,例如(旧的)世界状态,请将其删除。如果您意识到其中一些正在尝试验证重要的内容,请尝试确定这些测试是否正确执行了此操作。如果他们测试不正确,请让他们正确测试。

  3. 现在,您已经通过了良好的测试,请修复生产代码中的任何错误。

记住会计,每一行代码都是一种负债,但可能被错误地估价为资产。该delete键可以创造很多的价值你的公司。


团队风格的分类想法非常好!

好主意,但OP已经说过他没有资源进行大量分析,因此很遗憾,他将无法使用它们。
TMN

分流是关于将有限的资源分配到它们将创造最大价值的地方。这里有分流和软件的主题相关的博客文章:softwaretestingclub.com/profiles/blogs/...
艾伦·霍尔

5

200-300个损坏的测试(可能损坏多年)。

哎哟! 我曾经遇到过类似的情况,但是有7项测试失败,因此团队开始忽略了由于“总是嘎吱作响”的心态而失败了几个月的事实。

我的目标是100%通过测试,这样我们就可以打破单元测试失败的基础,但是直到解决了失败的测试之后我才能做到。

尽管我只是团队中的初级开发人员,但我仍然痴迷于类似的目标,因为我注意到堆积如山,在过去的几个月中,更多的测试失败了。我希望我们将这些警告从“警告”转变为构建错误(也许对团队的其他成员而言有些令人讨厌)。

我想我们应该用我们知道的任何东西记录破损测试的状态,然后完全删除或忽略破损测试,并输入一个较低优先级的错误/工作项来调查和修复它们。然后,我们将达到100%的水平,并开始从其他测试中获得真正的价值,如果我们有维护/重构的意外之财,我们将能够再次进行选择。

这些也是我的想法。您可以暂时禁用所有这些错误的测试,然后慢慢访问它们并逐步修复它们。即使您认为这些修补程序真的很重要,也要安排这些修补程序,即使它们的优先级较低,也很重要,因为这样的项目很容易就可以不修复。我的首要任务是确保不会引入任何失败的新测试。

像任何警告一样,如果它们不破坏构建,它们往往会迅速堆积。这是假设这种团队动态的情况下,忽略警告的习惯(在这种情况下为失败的测试)可以迅速导致引入更多警告,并减少了将警告保持为零的诱惑。

一个非常尽责的团队可能不会遇到这些问题,并且避免引入新的警告(测试中出现新的失败),但是绝对放心一点,通过将这些问题变成必须在解决问题之前解决的错误,从而采取预防策略,绝对是安全的。合并过程。

因此,我的建议与您的建议相同(尽管只有很强烈的意见-也许可以用度量标准和更科学的答案来支持)。禁用这些旧测试,并按计划进行修复。第一要务是通过确保当前成功的测试在开始失败时最终不会被忽略,从而确保该问题不会堆积并变得更糟。


4

从某种程度上来说,你很幸运。最好有个失败且不应该的测试(它们至少会向您发出警告,警告您有问题)比通过且不应该的测试(给您一种错误的安全感)更好。
当然,如果您拥有前者,那么很有可能您也拥有后者(因此测试可以通过,但应该失败)。

如前所述,暂时禁用那些失败的测试,但让它们在您的测试日志中打印一条消息,作为有关它们的不断提醒。
但是,您绝对应该找到遍及整个测试套件的资源,以查找和淘汰通过和不应该通过的测试,因为每个测试都意味着您的代码中存在一个错误,您目前无法在自己的代码中检测到该错误测试周期。

使用笼罩在代码库中的乌云,您可能能够获得一些预算,以对测试进行全面审查,如果您进行得当,并且不只是告诉他们您认为应该考虑一些测试,因为它们似乎在不应该进行的测试中失败,但是您不相信测试可以正确检测代码中的错误,因此不能信任测试集来执行其工作。
当我在上一家公司工作时,我进行了这样的审查,发现数百个测试编写的代码假设做错了正确的假设,导致代码(使用相同的错误假设编写)通过了测试确实不应该。修复此问题后,解决了许多令人讨厌的极端情况错误(尽管大多数情况并不严重),这些错误可能导致某些重要系统崩溃。


3

任何失败的单元测试都应导致构建损坏。善于实现它并设定目标。除了持续不断的虚假警报的源头之外,人类的大脑几乎无法完全忽略任何事情。

扔掉这些测试,不要回头。如果它们已经失败了好几年,并且现在还没有得到解决,那么它们就不是优先事项。

至于部族知识,如果仍然有部族知识的人还在,他们应该已经修复了失败的测试。如果不是,那么这些也不是优先事项。

如果没有部落知识,那么您和您的团队就必须拥有逻辑的所有权。测试失败可能会误导而不是有所帮助-世界可能已经发生了变化。

创建相关的新测试并继续编写出色的代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.