a L*_*ner 1 testing tdd unit-testing testdrivendesign
根据维基百科以下是TDD中的步骤:
第1步:编写单元测试
第2步:运行单元测试
第3步:为模块编写代码
第4步:再次运行所有测试
第5步:清理代码
第6步:重复这些步骤
问题1:在TDD中我们主要编写单元测试.集成测试和系统测试在上述步骤中的适用范围是什么?
请考虑以下示例:
假设我们有一个我们必须开发的功能.然后根据TDD,我们将在短迭代中开发此功能.假设我们已将此功能划分为2个模块 - 模块1和模块2.我正在编写迭代步骤,根据上述步骤在TDD中开发这些模块.(问题2)请在以下步骤中纠正我错误的地方:
**迭代1:**
第1步:我们为模块1编写单元测试.
第2步:为模块1运行此单元测试(此测试将失败)
第3步:为模块1开发代码.
步骤4:再次运行模块1的单元测试(此测试将通过)
**迭代2:**
步骤1:为模块2编写单元测试
第2步:运行模块2的单元测试
第3步:为模块2编写代码
步骤4:运行模块1的单元测试和模块2的单元测试.(问题3:在这一步中,为什么我们运行模块1的单元测试,因为模块2正在测试中?如果你说这样做是因为测试无论模块2是否没有破坏模块1的功能,那么我的问题是,这里我们只测试模块2.它还没有与模块1集成,那么它将如何打破模块1?)
**迭代3:**
第1步:创建集成测试(我在这里吗?)
第2步:运行集成测试(它们将失败,因为模块1和模块2尚未集成)
步骤3:集成模块1和模块2
第4步:运行所有测试(模块1,模块2和集成测试的单元测试)
(问题4:为什么在这一步中我们运行模块1和2的单元测试?)
迭代4(所有模块集成时):
第1步:创建系统测试
第2步:运行系统测试(它们将失败)
第3步:( 问题5 :)我应该在这里编写什么代码作为系统测试,我们不编写任何代码,根据TDD原则,我们首先编写测试然后编写开发代码,那么我们将在这里编写什么代码?
在我看来,你的工作流程略微倒退.在优秀的" 面向成长的面向对象软件测试"一书中,建议您从更高级别的测试开始,通常是一个"集成测试",代表您要添加的功能,并使其成为您想要的行为的驱动因素.看到.
您知道在此集成测试通过时您已完成此功能.
一旦你有这个失败的测试(作者称之为外部循环),那么你就开始内部循环上的TDD过程,即为实现所需功能所需的类创建测试.你这样做是通过创建一个测试,编写代码使其通过.然后运行所有测试.可能你的外部测试仍然会失败.然后实现另一个单元测试,然后执行所需的实现.重复此过程,直到您创建了要传递的外部测试的所有必需类.
然后通过编写新的外部测试再次重复整个过程.
对我来说,最重要的事情是找到一个适合你的过程,并且务实.不要像任何事情那样强迫任何教条方法,编写软件会因你正在编写的东西,你正在编写它的人,可用的工具和许多其他因素而异.始终准备好根据自己的经验改变自己的流程并不断重新评估,并根据您与之合作并尊重您的经验.没有人拥有完美的解决方案,因为事情总能变得更好.
编写Rhino Mocks的人说他很少再使用模拟框架了.谁的家伙写在.NET依赖注入说,他很少使用IoC容器了.要灵活务实.
我发现我倾向于更多地关注外部集成测试,而不是专注于单元级测试,因为这会强制测试测试代码的行为而不是实现.我发现当我为每个实际的类都有一个测试类时,重构代码变得非常昂贵,因为我不仅要更改所有类,而且还必须同时重构所有测试.当测试集中在代码的逻辑单元的行为上时,通常当我重构该代码的类结构时,测试保持不变,因为我只重新组织内部结构,而不是外部行为.
@CarlManaster关于BDD的内容也非常重要.我发现BDD比TDD更有用,因为主要是从测试到行为的重点转移.行为是你想要的,而不是一大套测试(尽管这也很好.)
至于要运行哪些测试,对我来说,您可以更频繁地运行的测试越多越好.令人惊讶的是,"孤立"的变化经常会莫名其妙地导致其他东西破裂.将整个系统中的每一个变化的后果牢记在脑中并不是一件简单的事情,就像你可能想到的那样,即使是小型系统.
我首选的工具是NCrunch.它删除了编码的停止/构建/运行测试部分.你只需编写测试,编写代码.等几秒钟 变绿.重复.改变了我的生活; 价值加倍他的收费.