在TDD中,在编写空方法之前运行测试的优势是什么?

rod*_*dbv 23 tdd unit-testing visual-studio-2008

我看到很多TDD从业者遵循这个周期:

1)编写测试,就好像目标对象和API已经存在一样.

2)编译解决方案并看到它中断.

3)编写足够的代码以使其编译.

4)运行测试,看看是否失败.

5)编写足够的代码以使其通过.

6)运行测试并看到它通过

7)重构

步骤1和2的优点是什么?对于像Visual Studio这样的IDE,这真的很烦人,因为intellisense跳到那里试图猜测不存在的方法和属性.

我通常从第3步开始,让我的所有方法都抛出NotImplementedException,这对我来说似乎很好,但也许我错过了一些东西.

编辑以澄清:这不是一个问题,为什么我应该看到测试在通过之前失败; 从第3步开始,这是完全有道理的.我的问题是为什么甚至在此之前人们会在单元测试中调用API中不存在的方法(因此VS将显示红色波形,或者将整个方法名称描绘为红色等)并尝试编译.对我而言,VS告诉我该方法不存在的事实已经足够了.

Cor*_*Foy 18

然后首先编写方法名称来尝试它.通过首先编写测试和方法,我发现它迫使我真正考虑API,并且我可以轻松地更改名称,而不必担心已编写的代码.我的建议是尽量不遵守规则,并监控发生的情况.如果发现它会导致问题,请切换回来.如果没有,你现在就有了一种新的工作方式.

还要记住,当您第一次了解事物时,通常需要一套明确的规则来为您提供背景信息.当您开始从初学者转向更高级时,您将获得更多背景并能够进行调整.这听起来就像你在哪里.


Jus*_*ard 12

我是TDD从业者,我认为你做这件事的方式很好.看到测试失败是重要的部分,而不是看到代码无法编译.

试试这个修改后的顺序:

1)在注释中编写测试,就好像目标对象和API已经存在一样.

2)编写足够的API代码进行编译.

3)取消注释您的测试代码.

4)运行测试并看到它失败.

5)编写足够的代码以使其通过.

6)运行测试并看到它通过

7)冲洗并重复......

这样你仍然可以先获得思考测试的好处,而不是先实现.


Bri*_*con 10

使用JUnit的Eclipse中的工作流程(与具有MSTest的Visual Studio相反)是步骤1-3最有意义的地方.然后,第3步就是使用Eclipse的快速修复功能(Ctrl-1)根据刚刚编写的单元测试生成存根代码.

DoesntExistYet someObject = new DoesntExistYet();
int result = someObject.newMethod("123");
assertEquals(123,result);

第一行的快速修复将自动创建DoesntExistYet类(让您首先通过向导进行调整),下一个快速修复将为您创建newMethod,根据您使用它的方式适当地计算出签名.

因此,通过所有自动化使事情变得更容易,您可以继续使用人们提到的有关如何使用它来规划API的其他优势.


Rob*_*ams 10

我想每个人都缺少一个关键点 - 你怎么知道所需的方法还不存在?编写一个单元测试,调用一个不应该存在的方法,然后观察它失败,验证你的假设是否正确.在编译语言中,它应该无法编译.在非编译语言中,执行失败可能比检查API快得多.在大多数语言中,继承和多态可能导致存在未在API的心理模型中注册的方法.

在极少数情况下,您可能会发现该方法确实存在(并且IntelliSense可能也有助于检测它),您可能会发现需要更改所需的方法签名.或者,您甚至可能发现根本不需要编写该方法(可能是您上周写的,但是忘记了).

当然你可以选择跳过前两步,甚至完全免除TDD,但这些步骤确实有目的.尽管如此,我同意一般的观点,即我们总能从任何"最佳实践"中对这些步骤背后的基本原理的更多描述中受益.

编辑:从贾斯汀标准...

或者,如果您在开发人员团队中工作,并且没有亲自编写您依赖的代码.我认为这对大多数开发人员来说是一个相当常见的场景

编辑:来自senfo ...

如果你在跟踪基类中实现了哪些方法时遇到问题,那么我觉得你的继承层次结构太复杂了.我仍然投票支持你,因为我同意如果我从单元测试开始,我会花更多时间来验证方法是否已经存在.

@senfo:继承层次结构中的复杂性太多肯定会发生,但这是一个明显的解决方案的另一个问题.即使您现有的代码是完美的,从单元测试开始尝试调用可能不存在的方法仍然是有价值的,只是为了快速向自己证明它不存在.当然,跳过这一步是可以理解的 - 我可能会在我的测试行为不端的特定情况下回到它(在特定情况下验证我没有调用除了我刚刚写的内容之外的东西).