有人能解释一下“假装直到成功”吗?测试驱动开发中的方法?
当您采用“Fake It Until You Make IT”TDD 方法时,我很难理解代码的演变。
好吧,你伪造了它,假设你返回了一个常量,以便损坏的测试一开始是绿色的。然后你重构了你的代码。然后你运行相同的测试,显然它会通过,因为你伪造了它!
但如果测试通过了,你怎么能相信它,特别是当你知道你伪造了它时?
应该如何用真实的代码重构来重构伪造的测试,使其仍然可靠?
谢谢
I have a problem to understand the evolution of code when you have taken the "Fake It Until You Make IT" TDD approach.
Ok, you have faked it, let's say you returned a constant so that the broken test is green in the beginning. Then you re-factored your code. Then you run the same test which is going to pass obviously because you have faked it!
But if a test is passing how can you rely on that, especially when you know that you faked that?
How should the faked test be refactored with your real code refactoring so that it can still be reliable?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
简短的答案是:编写更多测试。
如果该方法返回一个常量(当它应该计算某些内容时),只需添加对具有不同结果的条件的测试即可。因此,假设您有以下内容:
并且
myLength
被实现为return 5
,然后您编写一个类似的(附加)测试,但传入相反,并断言输出为 6。当您编写测试时,您应该尝试对实现非常报复,并尝试编写一些暴露其缺点的内容。当您编写代码时,我认为您应该非常自由放任,并且只需要做很少的事情即可使那些令人讨厌的测试变得绿色。
The short answer is: write more tests.
If the method is returning a constant (when it should be calculating something), simply add a test for a condition with a different result. So, let's say you had the following:
and
myLength
was implemented asreturn 5
, then you write a similar (additional) test but pass in"foobar"
instead and assert that the output is 6.When you're writing tests, you should try to be very vindictive against the implementation and try to write something that exposes its shortcomings. When you're writing code, I think you're meant to be very laissez-faire and do as little is required to make those nasty tests green.
您首先创建一个单元测试来测试不存在的新功能。
现在,您对一个不存在的方法进行了单元测试。然后,您创建不执行任何操作的方法,并且单元测试可以编译,但当然会失败。
然后,您继续构建方法、底层功能等,直到单元测试成功。
这就是(某种)测试驱动开发。
您应该能够信任这一点的原因是您应该进行单元测试,以便它真正测试您的功能。当然,如果它只返回一个常量并且您只是对其进行测试,那么您就会遇到问题。但是,你的单元测试还没有完成。
您的单元测试应该(理论上)测试每一行。如果你做得很好,那么这应该可行。
You first create a unit test testing new functionality that does not exist.
Now, you have a unit test to a non existing method. You then create that method that doesn't do anything and your unit test compiles, but of course, fails.
You then go on building your method, underlying functionality etc until your unit test succeeds.
That's (kind of) test driven development.
The reason you should be able to trust on this is that you should make your unit test so that it actually tests your functionality. Of course, if it just returns a constant and you just test on that, you have a problem. But then, your unit test is not complete.
Your unit tests should (in theory) test every line. And if you've done that OK, this should work.
假装它直到你做到它说要编写尽可能简单的东西来通过当前的测试。通常,当您为新功能编写单个测试用例时,最简单的可能就是返回一个常量。当如此简单的东西满足您的测试时,那是因为您(还)没有足够的测试。因此,正如 @Andrzej Doyle 所说,编写另一个测试。现在您正在开发的功能需要一些逻辑。也许这次最简单的事情就是编写非常基本的 if-else 逻辑来处理两个测试用例。你知道你在假装,所以你知道你还没有完成。当编写实际代码来解决您的问题比扩展您的假代码以覆盖另一个测试用例变得更简单时 - 这就是您所做的。并且您有足够的测试用例来确保您正确编写它。
Fake it 'til you make it says to write the simplest possible thing to pass your current tests. Frequently, when you've written a single test case for a new feature, that simplest possible thing is to return a constant. When something that simple satisfies your tests, it's because you don't (yet) have enough tests. So write another test, as @Andrzej Doyle says. Now the feature you're developing needs some logic to it. Maybe this time the simplest possible thing is to write very basic if-else logic to handle your two test cases. You know you're faking it, so you know you're not done. When it becomes simpler to write the actual code to solve your problem than to extend your fake to cover yet another test case - that's what you do. And you've got enough test cases to make sure you're writing it correctly.
这可能指的是使用模拟/存根/假货与您的测试系统/类进行协作的实践。
在这种情况下,您“伪造”协作者,而不是您正在测试的东西,因为您没有该协作者接口的实现。
因此,你可以假装它,直到你“成功”,这意味着你在一个具体的类中实现它。
This may be referring to the practice of using mocks/stubs/fakes with which your system/class under test collaborates.
In this scenario, you "fake" the collaborator, not the thing that you are testing, because you don't have an implementation of this collaborator's interface.
Thus, you fake it until you "make it," meaning that you implement it in a concrete class.
在 TDD 中,所有需求都以测试的形式表达。如果你伪造了一些东西并且所有测试都通过了,那么你的要求就得到了满足。如果这没有给您带来预期的行为,那么您还没有将所有需求表达为测试。
如果您此时继续伪造内容,您最终会发现最简单的解决方案是实际解决问题。
In TDD, all the requirements are expressed as tests. If you fake something and all tests pass, your requirements are fulfilled. If this is not giving you the expected behavior, then you have not expressed all your requirements as tests.
If you continue faking stuff at this point, you will eventually notice that the easiest solution would be to actually solve the problem.
当您重构代码时,您将从返回常量值切换为返回派生/计算的变量形式的表达式。
假设第一次编写正确,该测试对于新重构的实现仍然有效,并且不必重构。
了解 Fake It 背后的动机很重要:这与先编写断言类似,但生产代码除外。它让你变得绿色,让你专注于以尽可能简单的方式将假货变成有效的表达,同时仍然通过测试。当实施不明显时,在放弃并切换到三角测量之前,这是首先要尝试的事情。
When you refactor the code, you are switching from returning a constant value to returning an expression in terms of variables, which are derived/calculated.
The test, assuming it was written correctly the first time around, would still be valid for your newly refactored implementation and does not have to be refactored.
It's important to understand the motivation behind Fake It: It's similar to writing the Assert first, except for your production code. It gets you to green, and lets you focus on turning the fake into a valid expression in the simplest way possible while still passing the test. It's the first thing to try when implementation is not obvious, before you give up and switch to Triangulation.