与 TDD 的对抗/天真的配对:效果如何?

发布于 2024-07-05 20:43:28 字数 469 浏览 9 评论 0原文

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

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

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

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

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

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

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

A friend of mine was explaining how they do ping-pong pairing with TDD at his workplace and he said that they take an "adversarial" approach. That is, when the test writing person hands the keyboard over to the implementer, the implementer tries to do the bare simplest (and sometimes wrong thing) to make the test pass.

For example, if they're testing a GetName() method and the test checks for "Sally", the implementation of the GetName method would simply be:

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

Which would, of course, pass the test (naively).

He explains that this helps eliminate naive tests that check for specific canned values rather than testing the actual behavior or expected state of components. It also helps drive the creation of more tests and ultimately better design and fewer bugs.

It sounded good, but in a short session with him, it seemed like it took a lot longer to get through a single round of tests than otherwise and I didn't feel that a lot of extra value was gained.

Do you use this approach, and if so, have you seen it pay off?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦里兽 2024-07-12 20:43:28

我就用过这个方法。 它并不适用于所有配对; 有些人只是天生抵制,不会给它一个诚实的机会。 然而,它可以帮助您正确地进行 TDD 和 XP。 您想尝试慢慢向代码库添加功能。 您不想编写需要大量代码才能满足的庞大整体测试。 你想要一堆简单的测试。 您还需要确保定期在双方之间来回传递键盘,以便双方都参与其中。 通过对抗性配对,你可以同时做到这两点。 简单的测试导致简单的实现,代码构建缓慢,整个过程两个人都参与。

I've used this approach. It doesn't work with all pairs; some people are just naturally resistant and won't give it an honest chance. However, it helps you do TDD and XP properly. You want to try and add features to your codebase slowly. You don't want to write a huge monolithic test that will take lots of code to satisfy. You want a bunch of simple tests. You also want to make sure you're passing the keyboard back and forth between your pairs regularly so that both pairs are engaged. With adversarial pairing, you're doing both. Simple tests lead to simple implementations, the code is built slowly, and both people are involved throughout the whole process.

东京女 2024-07-12 20:43:28

这可能非常有效。

它迫使您更多地考虑必须编写哪些测试才能让其他程序员编写您所需的正确功能。

你经常通过键盘一点一点地构建代码,

这可能非常累人和耗时,但我发现这种情况很少见,我不得不返回并修复像这样编写的任何代码中的错误

It can be very effective.

It forces you to think more about what test you have to write to get the other programmer to write the correct functionality you require.

You build up the code piece by piece passing the keyboard frequently

It can be quite tiring and time consuming but I have found that its rare I have had to come back and fix a bug in any code that has been written like this

渔村楼浪 2024-07-12 20:43:28

它基于团队的个性。 每个团队都有自己的个性,这是其成员的总和。 你必须小心,不要以一种优越感来实施被动攻击的实施方式。 一些开发人员对类似的实现感到沮丧

返回“莎莉”;

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

It is based on the team's personality. Every team has a personality that is the sum of its members. You have to be careful not to practice passive-aggressive implementations done with an air of superiority. Some developers are frustrated by implementations like

return "Sally";

This frustration will lead to an unsuccessful team. I was among the frustrated and did not see it pay off. I think a better approach is more oral communication making suggestions about how a test might be better implemented.

梅窗月明清似水 2024-07-12 20:43:28

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

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

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

那么我打赌它被命名为“testGetNameReturnsNameField”。 这是一个坏名字,但并非立即显而易见。 此测试的正确名称是“testGetNameReturnsSally”。 这就是它的作用。 任何其他名字都会让你产生一种虚假的安全感。 所以这个测试的名字很糟糕。 问题不在于代码。 问题甚至不是测试。 问题是测试的名称。

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

因此,实施者有责任证明测试人员的选择不当。 实现者还有责任只编写测试要求的内容。

生产中出现如此多的错误并不是因为代码做得比预期少,而是因为它做得更多。 是的,对所有预期的情况都有单元测试,但没有对代码所做的所有特殊边缘情况进行测试,因为程序员认为“我最好也这样做,我们可能需要那个”,然后忘记了它。 这就是为什么 TDD 比 test-after 效果更好。 这就是为什么我们在峰值后丢弃代码的原因。 该代码可能会执行您想要的所有操作,但它可能会执行您认为需要但后来忘记的操作。

迫使测试编写者测试他们真正想要的东西。 只编写使测试通过的代码,仅此而已。

RandomStringUtils 是你的朋友。

(First, off, Adversarial TDD should be fun. It should be an opportunity for teaching. It shouldn't be an opportunity for human dominance rituals. If there isn't the space for a bit of humor then leave the team. Sorry. Life is to short to waste in a negative environment.)

The problem here is badly named tests. If the test looked like this:

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

Then I bet it was named "testGetNameReturnsNameField". This is a bad name, but not immediately obviously so. The proper name for this test is "testGetNameReturnsSally". That is what it does. Any other name is lulling you into a false sense of security. So the test is badly named. The problem is not the code. The problem is not even the test. The problem is the name of the test.

If, instead, the tester had named the test "testGetNameReturnsSally", then it would have been immediately obvious that this is probably not testing what we want.

It is therefore the duty of the implementor to demonstrate the poor choice of the tester. It is also the duty of the implementor to write only what the tests demand of them.

So many bugs in production occur not because the code did less than expected, but because it did more. Yes, there were unit tests for all the expected cases, but there were not tests for all the special edge cases that the code did because the programmer thought "I better just do this too, we'll probably need that" and then forgot about it. That is why TDD works better than test-after. That is why we throw code away after a spike. The code might do all the things you want, but it probably does somethings you thought you needed, and then forgot about.

Force the test writer to test what they really want. Only write code to make tests pass and no more.

RandomStringUtils is your friend.

猫九 2024-07-12 20:43:28

我有时喜欢它 - 但不要一直使用这种风格。 有时可以很好地改变节奏。 我认为我不想一直使用这种风格。

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

I like it some of the time - but don't use that style the entire time. Acts as a nice change of pace at times. I don't think I'd like to use the style all of the time.

I've found it a useful tool with beginners to introduce how the tests can drive the implementation though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文