我的一个朋友正在解释他们如何在他的工作场所与 TDD 进行乒乓配对,他说他们采取的是“对抗性”方法。也就是说,当测试编写人员将键盘交给实现者时,实现者尝试做最简单的(有时是错误的事情)来使测试通过。

例如,如果他们正在测试 GetName() 方法并且测试检查“Sally”,则 GetName 方法的实现将很简单:

public string GetName(){
    return "Sally";
}

当然,这会通过测试(天真地)。

他解释说,这有助于消除检查特定固定值而不是测试组件的实际行为或预期状态的幼稚测试。它还有助于推动创建更多测试,最终实现更好的设计和更少的错误。

听起来不错,但在与他的短暂交谈中,似乎通过一轮测试所花费的时间比其他情况要长得多,而且我并没有觉得获得了很多额外的价值。

您是否使用这种方法?如果使用,您是否看到它得到了回报?

有帮助吗?

解决方案

这是基于团队的个性。每个团队的个性都是其成员的总和。你必须要小心,不要以优势的方式练习被动式攻击性实施。一些开发人员对像

这样的实现感到沮丧
  

return" Sally";

这种挫败感会导致团队失败。我是沮丧的人之一,并没有看到它的回报。我认为更好的方法是更多的口头交流,就如何更好地实施测试提出建议。

其他提示

它非常有效。

它迫使您更多地考虑要编写的测试,以便让其他程序员编写您需要的正确功能。

您经常通过键盘逐段构建代码

它可能非常累人且耗时但我发现它很少见,我必须回来修复任何代码编写的错误

我用过这种方法。它不适用于所有对;有些人只是自然抗拒,不会给它一个诚实的机会。但是,它可以帮助您正确地进行TDD和XP。您想尝试慢慢地向代码库添加功能。你不想写一个巨大的单片测试,需要大量的代码才能满足。你想要一堆简单的测试。您还需要确保定期在对子之间来回传递键盘,以便两对都能够啮合。通过对抗配对,你可以做到这两点。简单的测试导致简单的实现,代码构建缓慢,并且两个人都参与整个过程。

我有时喜欢它 - 但是不要一直使用那种风格。有时候会改变节奏。我觉得我不想一直使用这种风格。

我发现它是一个有用的工具,初学者可以介绍测试如何推动实现。

(首先,关闭,对抗性TDD应该很有趣。它应该是教学的机会。它不应该是人类统治仪式的机会。如果没有一点点幽默的空间那么离开团队对不起。在消极的环境中,生命就是浪费。)

这里的问题是严格命名的测试。如果测试看起来像这样:

foo = new Thing("Sally")
assertEquals("Sally", foo.getName())

然后我打赌它被命名为“ testGetNameReturnsNameField ”。这是一个坏名字,但不是很明显。此测试的正确名称是“ testGetNameReturnsSally ”。这就是它的作用。任何其他名称都会让你陷入虚假的安全感。所以这个测试名字很糟糕。问题不在于代码。这个问题甚至都不是考验。问题是测试的名称。

相反,如果测试人员将测试命名为“ testGetNameReturnsSally ”,那么很明显,这可能不会测试我们想要的内容。

因此,实施者有责任证明测试人员选择不当。实现者还有义务只写出测试对它们的要求。

生产中出现的这么多错误并不是因为代码的效果低于预期,而是因为它做得更多。是的,对所有预期的情况都进行了单元测试,但是没有对代码所做的所有特殊边缘情况的测试,因为程序员认为“我最好也这样做,我们可能需要”。然后忘了它。这就是为什么TDD比后续测试更好的原因。这就是为什么我们在尖峰之后扔掉代码。代码可能会做你想要的所有事情,但它可能会做你认为需要的事情,然后忘了。

强制测试编写者测试他们真正想要的东西。只编写代码才能使测试通过,不再需要。

RandomStringUtils是你的朋友。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top