I like the instant feedback from the test, that's reward enough for me. If I can reproduce a bug in a test that's a good feeling, I know I'm headed in the right direction as opposed to guessing and possibly wasting my time.
I like working Test-First because I feel like it keeps me more in tune with what the code is actually doing as opposed to guessing based on a possibly inaccurate mental model. Being able to confirm my assumptions iteratively is a big payoff for me.
I find that writing tests helps me to sketch out my approach to the problem at hand. Often, if you can't write a good test, it means you haven't necessarily thought enough about what it is that you're supposed to be doing. The satisfaction of being confident that I know how to tackle the problem once the tests are written is rather useful.
I'll let you know when I find a method that works. :-)
But seriously, I think your "practice until it feels natural" comment pretty much hits the nail on the head. A 4 line test may appear trivial, but as long as what you are testing represents a real failure point then it is worth doing.
One thing I have found to be helpful is to include code coverage validation as part of the build process. If I fail to write tests, the build will complain at me. If I continue failing to write tests, the continuous integration build will "error out" and everyone nearby will hear the sound I have wired to the "broken build" notification. After a few weeks of "Good grief... You broke it again?", and similar comments, I soon started writing more tests to avoid embarrassment.
One other thing (which only occurred to me after I had submitted the answer the first time) is that once I really got into the habit of writing tests first, I got great positive reinforcement from the fact that I could deliver bug-fixes and additional features with much greater confidence than I could in my pre-automated-test days.
1) You pair with somebody else in your team. One person writes the test, the other implements.
It's called "ping-pong" pairing.
Doing this will force you to discuss design and work out what to do.
Having this discussion also makes it easier to see what tests you're going to need.
2) When I'm working on my own, I like to try out chunks of code interactively. I just type them in at the ruby prompt. When I'm experimenting like this I often need to set up some data for experimenting with, and some printout statements to see what the result is.
These little, self-contained throwaway experiments are usually:
a quick way to establish the feasibility of an implementation, and
I think the important part of keeping yourself in check as far as TDD is concerned is to have the test project set up properly. That way adding a trivial test case is indeed trivial.
If to add a test you need to first create a test project, then work out how isolate components, when to mock things, etc, etc it gees into too hard basket.
So I guess it comes back to having unit tests fully integrated into your development process.
When I first started doing TDD around 2000, it felt very unnatural. Then came the first version of .net and the JUnit port of NUnit, and I started practice TDD at the Shu level (of Shu-Ha-Ri), which meant test (first) everything, with the same questions as yours.
A few years later, at another workplace, together with a very dedicated, competent senior developer, we took the steps necessary to reach the Ha level. This meant for example, not blindly starring at the coverage report, but question "is this kind of test really useful, and does it add more value than it costs?".
Now, at another workplace, together with yet another great colleague, I feel that we're taking our first steps towards the Ri level. For us that currently means a great focus on BDD/executable stories. With those in place verifying the requirements at a higher level, I feel more productive, since I don't need to (re-)write a bunch of unit tests each time a class' public interface needs to change, replace a static call with an extension method, and so on.
Don't get me wrong, the usual TDD class tests still is used and provides great value for us. It's hard to put in words, but we're just so much better at "feeling" and "sensing" what tests makes sense, and how to design our software, than I was capable of ten years ago.
发布评论
评论(8)
我喜欢测试的即时反馈,这对我来说已经足够了。如果我能够在测试中重现错误,那是一种很好的感觉,我知道我正朝着正确的方向前进,而不是猜测并可能浪费我的时间。
我喜欢“测试优先”,因为我觉得它让我更了解代码实际在做什么,而不是根据可能不准确的心理模型进行猜测。能够反复确认我的假设对我来说是一个巨大的回报。
I like the instant feedback from the test, that's reward enough for me. If I can reproduce a bug in a test that's a good feeling, I know I'm headed in the right direction as opposed to guessing and possibly wasting my time.
I like working Test-First because I feel like it keeps me more in tune with what the code is actually doing as opposed to guessing based on a possibly inaccurate mental model. Being able to confirm my assumptions iteratively is a big payoff for me.
我发现编写测试可以帮助我勾勒出解决手头问题的方法。通常,如果您不能编写好的测试,则意味着您没有充分考虑自己应该做什么。一旦编写了测试,我就知道如何解决问题,这种满足感是相当有用的。
I find that writing tests helps me to sketch out my approach to the problem at hand. Often, if you can't write a good test, it means you haven't necessarily thought enough about what it is that you're supposed to be doing. The satisfaction of being confident that I know how to tackle the problem once the tests are written is rather useful.
当我找到有效的方法时,我会告诉你。 :-)
但说真的,我认为你的“练习直到感觉自然”的评论几乎一语中的。 4 行测试可能看起来微不足道,但只要您测试的内容代表真正的故障点,那么就值得做。
我发现有用的一件事是将代码覆盖率验证作为构建过程的一部分。如果我未能编写测试,构建就会向我抱怨。如果我继续无法编写测试,持续集成构建将“出错”,并且附近的每个人都会听到我连接到“损坏的构建”通知的声音。经过几周的“天啊……你又把它弄坏了?”和类似的评论之后,我很快开始编写更多的测试以避免尴尬。
另一件事(只有在我第一次提交答案后才发生在我身上)是,一旦我真正养成了先编写测试的习惯,我就可以提供错误修复和额外的事实,从而得到了很大的积极强化与我在自动化测试前的日子相比,我对这些功能更有信心。
I'll let you know when I find a method that works. :-)
But seriously, I think your "practice until it feels natural" comment pretty much hits the nail on the head. A 4 line test may appear trivial, but as long as what you are testing represents a real failure point then it is worth doing.
One thing I have found to be helpful is to include code coverage validation as part of the build process. If I fail to write tests, the build will complain at me. If I continue failing to write tests, the continuous integration build will "error out" and everyone nearby will hear the sound I have wired to the "broken build" notification. After a few weeks of "Good grief... You broke it again?", and similar comments, I soon started writing more tests to avoid embarrassment.
One other thing (which only occurred to me after I had submitted the answer the first time) is that once I really got into the habit of writing tests first, I got great positive reinforcement from the fact that I could deliver bug-fixes and additional features with much greater confidence than I could in my pre-automated-test days.
我发现的最简单的方法就是大量使用 TDD。在某些时候,在没有单元测试的情况下编写代码会变得非常非常紧张。
此外,尝试关注交互或行为测试而不是基于状态的测试。
Easiest way I've found is to just use TDD a lot. At some point, writing code without unit tests becomes a very, very nervous activity.
Also, try to focus on interaction or behavioral testing rather than state-based testing.
佩戴绿色腕带
wear a green wristband
1) 您与团队中的其他人结对。一个人编写测试,另一个人实施。
这就是所谓的“乒乓”配对。
这样做将迫使您讨论设计并找出该怎么做。
进行此讨论还可以更轻松地了解您将需要哪些测试。
2)当我自己工作时,我喜欢以交互方式尝试代码块。我只是在 ruby 提示符下输入它们。当我进行这样的实验时,我经常需要设置一些用于实验的数据,以及一些打印输出语句来查看结果是什么。
这些小型的、独立的一次性实验通常是:
1) You pair with somebody else in your team. One person writes the test, the other implements.
It's called "ping-pong" pairing.
Doing this will force you to discuss design and work out what to do.
Having this discussion also makes it easier to see what tests you're going to need.
2) When I'm working on my own, I like to try out chunks of code interactively. I just type them in at the ruby prompt. When I'm experimenting like this I often need to set up some data for experimenting with, and some printout statements to see what the result is.
These little, self-contained throwaway experiments are usually:
我认为就 TDD 而言,控制自己的重要部分是正确设置测试项目。这样添加一个简单的测试用例确实是微不足道的。
如果要添加测试,您需要首先创建一个测试项目,然后弄清楚如何隔离组件、何时模拟事物等等,这太难了。
所以我想这又回到了将单元测试完全集成到您的开发过程中。
I think the important part of keeping yourself in check as far as TDD is concerned is to have the test project set up properly. That way adding a trivial test case is indeed trivial.
If to add a test you need to first create a test project, then work out how isolate components, when to mock things, etc, etc it gees into too hard basket.
So I guess it comes back to having unit tests fully integrated into your development process.
当我在 2000 年左右第一次开始做 TDD 时,感觉很不自然。然后出现了 .net 的第一个版本和 NUnit 的 JUnit 端口,我开始在 Shu 级别练习 TDD(Shu-Ha-Ri),这意味着(首先)测试所有内容,并使用与您相同的问题。
几年后,在另一个工作场所,我们与一位非常敬业、有能力的高级开发人员一起,采取了达到 Ha 级别所需的步骤。例如,这意味着不要盲目关注覆盖率报告,而是要问“这种测试真的有用吗?它增加的价值是否大于成本?”。
现在,在另一个工作场所,与另一位出色的同事一起,我觉得我们正在向 Ri 级别迈出第一步。对于我们来说,目前这意味着要高度关注 BDD/可执行故事。通过在更高级别上验证需求,我感觉更有效率,因为每次类的公共接口需要更改时,我不需要(重新)编写一堆单元测试,将静态调用替换为扩展方法等等。
不要误会我的意思,通常的 TDD 类测试仍然被使用,并且为我们提供了巨大的价值。这很难用语言来表达,但我们比十年前更擅长“感觉”和“感知”测试的意义以及如何设计我们的软件。
When I first started doing TDD around 2000, it felt very unnatural. Then came the first version of .net and the JUnit port of NUnit, and I started practice TDD at the Shu level (of Shu-Ha-Ri), which meant test (first) everything, with the same questions as yours.
A few years later, at another workplace, together with a very dedicated, competent senior developer, we took the steps necessary to reach the Ha level. This meant for example, not blindly starring at the coverage report, but question "is this kind of test really useful, and does it add more value than it costs?".
Now, at another workplace, together with yet another great colleague, I feel that we're taking our first steps towards the Ri level. For us that currently means a great focus on BDD/executable stories. With those in place verifying the requirements at a higher level, I feel more productive, since I don't need to (re-)write a bunch of unit tests each time a class' public interface needs to change, replace a static call with an extension method, and so on.
Don't get me wrong, the usual TDD class tests still is used and provides great value for us. It's hard to put in words, but we're just so much better at "feeling" and "sensing" what tests makes sense, and how to design our software, than I was capable of ten years ago.