代码之家  ›  专栏  ›  技术社区  ›  Kevin Won

测试失败时,代码基与测试断言问题的“正常”比率?

  •  10
  • Kevin Won  · 技术社区  · 16 年前

    我目前正在从事一个项目,其中包含一些相当重要的业务规则,在我们编写解决方案时,问题空间正在被“发现”(相当典型的混乱项目管理之类的事情)。我们有不错的测试覆盖率;一定要相信他们,以确保我们的重大变化不会炸毁任何东西。这种情况是单元测试狂热者们强调的,作为测试的一个主要例子,它可以帮助您在不使用单元测试的情况下,立即轻松地修改软件,减少缺陷,更快地完成测试。我不寒而栗地想到,如果没有测试套件,我将如何应对。

    我的问题是,虽然我肯定相信单元测试的价值(这个项目实际上是TDD,但它与这个问题并不密切),但我和其他人一样,对拥有那么多代码来摸索和维护(即测试本身)的经典单元测试问题感到疑惑。再一次。 毫无疑问,在我看来,有了单元测试工具,这个特定的项目比没有它要好得多 ,我还担心测试的长期可维护性。

    1. 我们创建的测试列表要么是“依赖”的,要么是“独立”的
    2. 我们针对不同级别的代码 . 例如,我们的测试命中了“main”,测试命中了“main”将调用的所有方法。这使我们能够针对系统的细节和总体目标。如果“主”测试中断,则很难进行调试,但它们通常不是唯一中断的测试(详细测试也会中断)。遵循详细的测试并在它们中断时调试它们更容易,但是它们不足以知道重构是否会杀死系统(这就是“main”测试的目的)。
    3. . 较低级别的测试(真正的“工作单元”测试)是不够的。

    测试失败与实际的回归业务逻辑失败和单元测试无效之间存在比率 . 换句话说,有时测试失败是因为实际代码库中的回归错误,有时是因为单元测试断言不再有效,需要更改的是断言。大致看来,当测试失败时,这个特定项目的测试失败率大约为偶数(50%)。

    是否有人在他们的项目中跟踪了这个比率,如果是的话,关于这个比率你学到了什么(如果有的话)?我不确定它是否指示了什么,但我注意到,大约有一半的时间,测试失败导致我调整测试断言,而不是实际修复真实代码库中的回归错误。每当这种情况发生时,我都会觉得自己浪费了一天中的x个小时&我想知道我的测试方法是否能更有效。解决测试断言失败通常比解决实际的回归错误花费更长的时间,这既违反直觉又令人沮丧。

    编辑 请注意,这个问题是关于探索这个比率意味着什么以及你对这个比率的体验。什么时候“臭”??

    4 回复  |  直到 14 年前
        1
  •  3
  •   Esko Luontola    16 年前

    我注意到,大约有一半的时间,测试失败导致我调整测试断言,而不是实际修复真实代码库中的回归错误。

    当测试失败时,有三种选择:

    1. 执行失败,应该修复,
    2. 不再需要该测试(因为需求发生了变化),应该删除它。

    正确识别这三个选项中的哪一个很重要。我编写测试的方式是,以测试的名义记录测试指定/测试的行为,这样当测试失败时,我就能很容易地发现 为什么? http://blog.orfjackal.net/2010/02/three-styles-of-naming-tests.html

    就你而言,

    • 如果您需要更改测试,因为更改了需求和 只有几个测试 有时需要改变,然后一切正常(测试正常) isolated ,以便每个行为只通过一个测试来指定)。
    • 如果您需要更改测试,因为更改了需求和 在一个需要改变的时刻,那就是 test smell 你有很多测试测试相同的东西(测试是 隔离良好)。测试可能是测试 more than one interesting behaviour
    • 如果测试需要更改 ,那么测试的味道就是测试与实现细节的耦合太紧密了。试着编写以系统行为为中心的测试,而不是它的实现。 The article 我之前链接的应该给你一些想法。

    (有趣的是,如果你发现自己 重写 类,而不是更改它们,当需求更改时,它可以表示代码遵循得很好 SRP, OCP 以及其他设计原则。)

        2
  •  4
  •   S.Lott    16 年前

    “测试失败导致我调整测试断言,而不是在实际的代码库中修复回归错误。”

    “这让我觉得我一天浪费了x个小时”

    “解决测试断言失败通常比解决实际的回归错误需要更长的时间”

    不是开玩笑。当您的需求处于不断变化的状态时,将需求更改映射到测试结果更改需要花费大量的时间和精力。

    “这是。。。反直觉的。取决于你的直觉。我的直觉(经过18个月的TDD)是需求变更导致了设计变更,许多复杂的测试变更反映了设计变更。

    如果你的代码真的很好,它不会改变太多。当你花更多的时间在测试上而不是代码上时,就意味着你写了好的代码。

    当你花更多的时间试图让代码通过一组永远不会改变的测试时,代码的味道就会显现出来。想想这意味着什么。你写了测试,但你就是不能让代码通过。太可怕了。

    如果你花了一个小时编写测试,花了4个小时试图让代码通过测试,你要么得到了一个非常复杂的算法(并且应该把它分解成更多可测试的部分),要么你是一个糟糕的应用程序程序员。

    如果你花1小时写测试,花1小时让代码通过测试,那就好了。

    如果您因为需求更改而花了2小时修复测试,并且花了1/2小时调整代码以通过这些测试,那么您已经编写了一些非常好的代码。

        3
  •  1
  •   Yishai    16 年前

    我绝对赞同@S.Lott的回答。我只想指出,当规范建立在成堆的死树上时,当需求发生变化时,死树(或字处理器文件)不会像测试那样对你大喊大叫,所以一切都正常运行,只是你有一堆枯树,每个人都看着,说“文件是虚构的。”

    也就是说,在有些情况下,测试编写得不好或不实用,可能应该放弃。我发现,尤其是在TDD中,测试梳理出了设计,而且是真正的增量测试,现在设计和功能更进一步了,一些原始测试已经不再相关了。

    如果你认为修改一堆测试是“浪费了我一天的x个小时”,那么当你转到第二个测试时,你不会在第一个测试通过后再考虑它。这将使变革的成本更高。这可能是正确的决定,但是看着一个测试,说它被后来的事件克服了,然后放弃它,这没有错,只是不要把它当作一个廉价的出路。

        4
  •  0
  •   gareth_bowles    16 年前

    S洛特差不多都说了。我认为测试断言更改(T)与回归修复(R)的比率唯一能告诉您的是,您的需求有多不稳定(这将使T更高)与应用程序代码通过测试的成功率(这将影响R的值)的组合。这两个因素可以根据需求和开发过程的质量而独立变化。