将现有代码移至测试驱动开发

时间:2008-10-03 14:16:05

标签: c# tdd nunit

最近发现了这种开发方法,我发现它是一种相当不错的方法。所以,对于我的第一个项目,我有一个小DLL的代码(在C#.NET中,它的价值),我想为这段代码做一组测试,但我有点失去了如何和从哪里开始。

我正在使用NUnit和VS 2008,任何有关开始使用什么类的技巧,编写测试内容的提示,以及关于如何将代码转移到基于测试的开发的一般提示都将非常感激

5 个答案:

答案 0 :(得分:54)

请参阅Michael Feathers的书Working Effectively with Legacy Code

总之,将现有代码重构为可测试和测试的代码需要做很多工作;实际上有时需要做太多工作。这取决于代码库的大小,以及各种类和函数相互依赖的程度。

不经测试的重构将引入行为的变化(即错误)。纯粹主义者会说它不是真正的重构,因为缺乏检查行为不会改变的测试。

不是一次性将测试全面添加到整个应用程序中,而是在代码区域中添加测试。很可能你将不得不再次回到这些“热点”。

自下而上添加测试:测试很少的独立类和函数以确保正确性。

自上而下添加测试:将整个子系统测试为黑框,以查看其行为是否随代码更改而变化。因此,您可以逐步了解它们以了解正在发生的事情。这种方法可能会给你带来最大的好处。

在添加测试时,不要太在意“正确”行为是什么,要检测并避免行为发生变化。大型未经测试的系统通常具有可能看起来不正确的内部行为,但系统的其他部分依赖于此。

考虑隔离数据库,文件系统,网络等依赖项,以便在测试期间将它们换成模拟数据提供程序。

如果程序没有内部接口,这些行定义了一个子系统/层与另一个子系统/层之间的边界,那么您可能必须尝试引入这些接口并对它们进行测试。

此外,RhinomocksMoq等自动模拟框架可能有助于在此模拟现有类。我还没有真正发现在为可测试性设计的代码中需要它们。

答案 1 :(得分:10)

在没有测试的情况下将代码迁移到经过单元测试的环境中,

Working Effectively with Legacy Code是我的圣经,它还提供了很多有关如何使代码易于测试以及如何测试代码的深入见解。

我还发现Test Driven Development by ExamplePragmatic Unit Testing: in C# with NUnit可以很好地介绍该环境中的单元测试。

启动TDD的一个简单方法是从今天开始首先编写测试并确保无论何时需要触摸现有的(未经单元测试的)代码,都要编写通过测试来验证系统的现有行为在你改变它之前你可以重新运行那些测试,以增加你没有破坏任何东西的信心。

答案 2 :(得分:9)

我称之为“测试驱动的逆向工程”。

从“底部”开始 - 可以单独检查每个类并为其编写测试。如果有疑问,猜猜。

当你正向进行普通的TDD时,你会认为测试是神圣的,并假设代码可能已被破坏。有时测试是错误的,但是你的起始位置是代码。

当你进行TDRE时,代码是神圣的 - 直到你能证明代码有一个长期存在的错误。在相反的情况下,您可以围绕代码编写测试,调整测试直到它们工作并声明代码有效。

然后,你可以深入研究坏代码。一些不好的cade将有合理的测试用例 - 这只需要清理。然而,一些不好的代码也会有一个毫无意义的测试用例。这可能是您可以纠正的错误或笨拙的设计。

要判断代码是否真的错误,您还需要从整体测试用例开始。实际工作的实时数据是一个开始。此外,生成任何已知错误的实时数据也是一个很好的起点。

我编写了很少的代码生成器来将实时数据转换为单元测试用例。这样,我就有了一致的测试和重构基础。

答案 3 :(得分:4)

可通过随附的测试轻松发现可测试代码。如果有一些,它必须是可测试的。如果没有 - 假设相反。 ;)

这就是说:测试驱动开发(TDD)不是一个测试策略,而是一个设计策略。您首先编写的测试有助于设计类的接口,以及正确获取类(或子系统)的范围。

在TDD期间创建测试并稍后执行它们会做出很好的测试,但这只是该设计理念的一个(非常受欢迎的)副作用。

这就是说,期望你的代码有一些阻力来测试。聆听您的代码并更改界面以便轻松测试。当你开始编写测试时,你很可能会重新设计它。

答案 4 :(得分:1)

您的DLL提供某种服务。对于每项服务,在获得此服务之前您需要做什么,您应该通过哪些参数来获取此服务,您如何知道所请求的服务已正确执行?

获得这些问题的答案后,您可以编写第一个测试。这样的测试宁可被称为Characterization tests而不是单元测试,但如果没有使用TDD开发DLL,则可能比单元测试更容易编写。

M. Feathers的“有效地使用遗留代码”中也讨论了特征测试,这在其他答复中是推荐的。

此外,请务必在添加任何新代码之前编写失败的测试。