代码之家  ›  专栏  ›  技术社区  ›  Neil Moss

TDD可以留下哪些故障模式?

tdd
  •  11
  • Neil Moss  · 技术社区  · 14 年前

    请注意,我还没有看到TDD上的灯,也没有真正看到。 得到了 为什么它拥有主要支持者宣扬的所有利益?我并没有否认这一点——我只是有所保留,这可能是由于无知造成的。所以,只要你能纠正我,就一定要嘲笑下面的问题。

    使用TDD是否会使您自己容易受到实施过程中意想不到的副作用?“满足测试所需的最少代码量”的概念表明,在不必考虑全局的情况下,对特定问题进行最狭隘的思考。

    我在考虑那些持有或依赖于状态的对象(例如,内部字段值)。如果您有单独实例化一个对象的测试,初始化该对象,然后调用被测试的方法,您将如何发现 不同的 方法留下了一个将对第一个方法的行为产生不利影响的无效状态?如果我正确理解了问题,那么您不应该依赖于测试执行的顺序。

    我可以想象的其他故障包括流的非关闭、gdi+对象的非处理等。

    这是TDD的问题领域,还是集成和系统测试应该抓住这些问题?

    感谢您的期待……

    4 回复  |  直到 13 年前
        1
  •  7
  •   Jay    14 年前

    其中一些属于TDD领域。

    DanNorth说,没有测试驱动开发这样的东西;我们真正做的是示例驱动开发,只有在测试系统实现之后,示例才成为回归测试。

    这意味着,在设计一段代码时,需要考虑示例场景,并为每种情况设置测试。这些案例应包括数据无效的可能性,而不考虑 为什么? 数据可能无效。

    在练习TDD时,类似关闭流的操作可以并且应该完全覆盖。

    我们使用像函数这样的构造不仅可以减少重复,还可以封装功能。我们通过保持封装来减少副作用。我认为我们从设计的角度来考虑全局,但是当涉及到实现一个方法时,我们应该能够将我们的重点缩小到这个范围——功能单元。当我们开始处理外部性时,我们很可能会引入缺陷。

    不管怎样,这是我的看法;其他人可能会有不同的看法。

        2
  •  3
  •   Jay Bazuzi Buck Hodges    14 年前

    TDD并不是智能的替代品。 最好的程序员使用TDD会变得更好。最糟糕的程序员仍然很糟糕。

    事实上,你问这些问题是一个很好的迹象:这意味着你认真做好编程工作。

    “最小量”的概念 满足测试的代码“建议 狭隘地思考 一个特定的问题没有 必然会考虑更大的 图片。

    采取这种态度很容易,就像“我不需要测试这个,我确信它是有效的。”两人都很天真。

    这真的是采取小步骤,而不是说它早退。你仍在追求一个伟大的最终结果,但在这过程中你要小心 证明正当 验证 你写的每一段代码,都要经过测试。

    TDD的直接目标非常狭窄:“ 我如何才能确定我正在编写的代码是否符合我的预期? “如果你还有其他问题想回答(比如,“这在加纳会很顺利吗?”“我的程序足够快吗?”)然后你需要不同的方法来回答他们。

    我想的是那些能抓住或 取决于国家。

    你怎么会发现 不同的 方法留下了一个无效的 状态?

    依赖关系和状态很麻烦。它们会产生出现在最坏情况下的细微缺陷。它们使重构和未来的增强更加困难。它们使得单元测试不可行。

    幸运的是,TDD非常擅长帮助您生成将逻辑与依赖项和状态隔离开来的代码。这是“TDD”中的第二个“D”。

        3
  •  2
  •   Carl Manaster    14 年前

    “最小量”的概念 满足测试的代码“建议 狭隘地思考 一个特定的问题没有 必然会考虑更大的 图片。

    它暗示了这一点,但这不是它的意思。它的意思是强力眼罩 眼下 . 更大的图景就在那里,但会干扰手头的即时任务——所以要完全集中在即时任务上,以及 然后 担心接下来会发生什么。这张大图是存在的,在TDD中有说明,但我们在红色阶段暂停关注它。只要有一个失败的测试,我们的工作就是让测试通过。一旦它和所有其他的测试都通过了,那么是时候考虑全局、审视缺点、预测新的故障模式、新的输入了——然后编写一个测试来表达它们。这使我们回到红色,并重新缩小我们的焦点。让新的测试通过,然后为下一步留出百叶窗。

    是的,TDD给我们蒙上了眼罩。但它并没有使我们失明。

        4
  •  1
  •   mamoo    14 年前

    好问题。 这是我的两分钱,根据我的个人经验:

    可以使用TDD让自己 你的意外副作用 实施?

    是的,是的。TDD不是一个“成熟”的选择。它应该与其他技术一起使用,而且你必须牢记大局(不管你是否对此负责)。

    我想的是那些能抓住或 取决于状态(例如内部字段 价值观)。如果你有测试 单独实例化一个对象, 初始化该对象,然后调用 测试的方法,你会怎么做? 发现一个不同的方法已经离开 在一个无效的状态后面 对 第一种方法?如果我明白的话 很重要,那你不应该 依赖于测试执行的顺序。

    每种测试方法的执行都不应考虑之前执行的或之后执行的内容。如果不是这样的话,那么就有问题了(从TDD的角度来看)。

    谈到你的例子,当你写一个测试时,你应该用一个合理的细节知道你的输入是什么,预期的输出是什么。从定义的输入开始,在定义的状态下,检查所需的输出。你不能百分之百地保证在另一种状态下,同样的方法可以毫无错误地完成它的工作。然而,“意外”应该减少到最低限度。

    如果您设计了类,那么您应该明确地知道两个方法是否可以改变某些共享的内部状态和方式;更重要的是,如果这样 应该 真的会发生,或者如果有关于低内聚力的问题。

    不管怎样,“TDD”级的良好设计并不一定意味着您的软件已经很好地构建,正如Bob叔叔在这里所解释的那样,您需要更多:

    http://blog.objectmentor.com/articles/2007/10/17/tdd-with-acceptance-tests-and-unit-tests

    Martin Fowler写了一篇关于mocks vs stubs测试的有趣文章,其中涵盖了您正在讨论的一些主题:

    http://martinfowler.com/articles/mocksArentStubs.html#ClassicalAndMockistTesting