TDD入门?

时间:2009-07-28 16:27:42

标签: .net tdd code-coverage mocking

我们正处于尝试实施TDD的初始阶段。我演示了Visual Studio Team System代码覆盖/ TDD工具,团队对这些可能性感到兴奋。目前我们使用Devpartner进行代码覆盖,但我们想要消除它,因为它很昂贵。我们在TDD方面的经验非常有限,并且希望确保我们不会走错方向。目前我们使用SourceSafe进行源代码管理,但将在大约一年内迁移到Team System。

我可以告诉你我们的应用程序是以数据为中心的。我们有大约900个表,6000个存储过程和大约45GB的数据。我们有很多基于用户数据和系统中不同费率的计算。我们的很多代码也是基于时间(计算当前日期的兴趣)。其中一些计算非常复杂且非常密集(只有少数人知道其中一些的详细信息)。

我们希望实施TDD来解决质量保证问题。许多开发人员被迫在他们不熟悉的领域修复bug并最终破坏某些东西。开发人员也几乎不敢触摸,因为代码被系统中的所有内容使用。我们想要缓解这个问题。

我担心,因为我们的代码是以数据为中心的,因此实施TDD可能比大多数系统稍微复杂一些。我正在努力想出一个我可以向管理层提出的游戏计划,但我希望不要陷入一些TDD初学者的错误。此外,如果Team System中的工具/设施使TDD更加完整,那么这将是不错的,但我们不想等待Team System开始。

我们要问的第一个问题是,我们应该从Visual Studio中的工具开始吗?我看过帖子是人们抱怨视觉工作室中的内在工具(需要创建一个单独的项目来创建你的测试)但是关于visual studio中工具的一件事是他们是免费的和集成很好。如果我们决定使用XUnit,MBUnit或NUnit这样的其他路线,那么我们很可能会有一些可能的重大成本:

1)如果我们想要IDE集成(未提及我们的大多数代码是VB.Net)
---TestDriven.Net或Resharper或?????

2)如果我们想要代码覆盖率 --- NCover(其功能似乎相当昂贵)

此外,我在Visual Studio 2010中看到了一些非常酷的功能。比如能够进行输入测试(在表单上输入的数据)或记录用户所做的事情的能力,然后将其提供给您的单元测试重现问题。

此外,虽然我还没有完全掌握嘲弄对象的概念,但我知道很多人都认为这是必须的。问题是所有的模拟框架都可以插入到visual studio的TDD版本(MSTEST)中吗?

我告诉管理层我们应该只是添加回归测试(新开发或发现错误),但不要试图通过我们所有的代码并进行单元测试。这将是一个太大的项目。

无论如何,我会感激任何人的帮助。

7 个答案:

答案 0 :(得分:8)

要做的第一件事就是得到这本书:

Working Effectively with Legacy Code

对于这样一个大型项目,请阅读并内化。数据驱动应用程序上的TDD足够困难。在传统的,你需要一些认真的计划和努力。值得我认为,但它仍然是一个很大的曲线。

答案 1 :(得分:5)

不要急于上帝的缘故,不要试图强迫开发者做TDD。

否则 - 你会得到凌乱的低质量“测试”,这些测试将在几个月后被删除,开发人员将再也不想听到TDD了。

对TDD最重要的要求 - 良好如何编写测试的知识(非常明显的原因)。

第二项要求 - 良好使用过的技术知识 那是因为如果编写任何代码都很困难,那么设计代码就不可能了。

使用过的工具实际上并不重要。

P.S。大量遗留代码和以数据为中心的app =>一个很好的灾难模型。

答案 2 :(得分:4)

嗯,我首先建议你引进一家了解TDD的咨询公司,以帮助你的团队开始。如果您没有熟悉TDD,单元测试,模拟框架等的团队中的任何人,这一点尤为重要。我不确定您已从管理层或团队中获得了多少购买,但是您不知道我希望你的第一次尝试失败,因为通过聘请专家来帮助你采取这些初步步骤可以防止错误。

无论如何,我建议你从小做起并选择一个不是非常大的新项目。即使是较大项目的一小部分也能奏效。使用它作为让团队熟悉TDD的地方,并向管理层展示它是可行的。然后,一旦团队更精通,你就可以选择更大的项目。至于遗留代码,我建议你看一下这本书:

与遗产代码有效合作,Michael Feathers

另外我肯定会建议你看一下这本书:

单元测试艺术,Roy Osherove

它可能不是TDD书籍,但它是了解单元测试,模拟框架的好书,它甚至还有一章关于遗留代码。此外,它还提供了一些关于如何让团队和管理层购买的建议。它确实谈到了TDD,集成测试,组织代码库以及广泛关于什么是良好的单元测试。总而言之,这是一本很棒的读物。

希望这有帮助。

答案 3 :(得分:3)

1)我使用TestDriven.Net,我喜欢它,所以我为此+1 2)当在正确的思维框架中思考时,代码覆盖是有用的:
高代码覆盖率并不一定意味着高质量的单元测试,但是......
高质量的单元测试确实意味着高代码覆盖率

我只使用过NCover,所以不能推荐替代品。

关于嘲笑 - 一旦你掌握了它的含义以及它对你的真正含义,你就会看到它所带来的好处。也就是说,这意味着您不依赖于您正在测试的代码与外部依赖项的集成,还有助于缩短文本执行时间(例如,模拟数据访问层可防止与DB进行代价高昂的交互)。在我看来,这是一个重要的因素,好像测试需要很长时间才能运行,人们可以开始不打扰它们,如果这意味着他们必须等待太久!我使用NUnit,它支持内置的模拟。

将TDD方法绑定到持续集成环境(例如CruiseControl.NET),您将拥有非常强大且高效的设置。

当开始进行TDD /单元测试时,我总是建议为“现在”开始编写的代码编写测试,而不是过多地关注编写传统/现有代码的测试。总的来说要做的事情要困难得多,而且时间要花费更多,特别是如果代码在任何人的脑海中都是旧的/不新鲜的话!

更新:为了回应罗伯特的评论,再解释一下我的最后一点......

当您尝试启动并运行TDD /单元测试,并获得整个团队的动力时,您希望尽可能积极和高效。与新代码相比,在初始阶段对旧代码进行编写测试的代价是昂贵的,因为代码并不新鲜,它的确切复杂性很可能必须再次解决,而不一定是原始程序员。此外,您可能会发现很难为业务辩护,花费时间重新访问旧代码来为其编写测试,而不是处理新功能/修复真正的错误/问题。

它可能会成为一种消极的体验 - 一个开发人员负责编写旧代码的测试,他知道/记得很少会发现它更难做,因此他们的第一次体验不是积极的。在这种情况下你也需要小心,因为你最终会得到弱测试,这会给你带来虚假的信心。根据我的经验,绝对至关重要的是每个人都有这个积极的开端,否则其中的信心/动力会消退,最终结果会更糟。

实际上说你不应该为遗留代码添加测试 - 当我在没有任何测试的旧代码中或周围工作时,我会自己做位,提高测试覆盖率和质量。不同的是,我已经加入了这个过程,一个“信徒”。这是它的早期阶段,这是关键......因此我的观点是,在开始时不要将过多的重点放在遗留代码上。

答案 4 :(得分:3)

关于入门,我还建议阅读福勒的Refactoring。第一章给出了一个很好的感觉,即引入测试然后安全地引入变化意味着什么(尽管这里的重点是保持变化的行为)。此外,this对话描述了一些可以帮助提高代码可测试性的实践。 Misko Hevery还有编写可测试代码的this指南,该代码总结了该演讲。

从您的描述中,听起来好像您想要测试系统的核心部分 - 具有很多依赖关系的部分,其中变化是可怕的。根据数据访问与业务逻辑分离的程度,您可能需要重构一个代码更易测试的状态 - 在这里可以轻松快速地实例化测试数据集,以便单独验证逻辑。这可能是一项很大的工作,如果此处的更改很少且代码库已得到充分证明,则可能不值得付出努力。

我的建议是务实,并利用团队的经验找到最容易添加增值的测试的区域。我认为有许多专注的单元测试是提高质量的最佳方法,但使用集成或场景测试在更高级别测试代码可能更容易,当然在开始时。这样,您可以及早发现核心系统中的重大故障。清楚你的测试涵盖的内容。场景测试将涵盖大量代码,但可能不会出现细微的错误。

从SourceSafe迁移到Team System是一个很大的进步,有多大取决于你想在Team System中做多少。我认为使用Visual Studio内置的测试框架可以获得很多价值。例如,作为第一步,您可以为核心系统/核心用例实现一些基本测试套件。开发人员可以在工作时和签入之前在Visual Studio中自行运行。这些套件可以随着时间的推移逐渐扩展。稍后当您获得TFS时,您可以在签入时查看运行这些套件,并将其作为自动构建过程的一部分。无论具体工具如何,您都可以遵循类似的路径。

从一开始就要清楚,维护测试代码会有开销,并且设计良好的测试可以带来好处。我已经看到测试被复制粘贴然后稍微编辑的情况等。像这样的测试代码重复可能导致在实现小的产品代码更改时需要维护的测试代码行数量激增。这种麻烦会削弱进行测试所带来的好处。

Visual Studio 2008只会显示块覆盖率,尽管代码分析还会提供其他指标,例如每个程序集/类/方法的圈复杂度。通过测试获得高块覆盖率当然很重要,并且允许您轻松识别完全未经测试的系统区域。

但是,我认为重要的是要记住,高块覆盖率只是测试有效性的简单测量。例如,假设您编写了一个类来清除文件存档并保留5个最新文件。然后你编写一个测试用例,检查你是否从10个文件开始然后运行你剩下的purger 5.通过测试的实现可以删除最新的文件,但可以很容易地给出100%的覆盖率。此测试仅验证其中一项要求。

答案 5 :(得分:1)

有效地使用Yishai推荐的遗产代码100个大拇指。当你使用.NET时我也推荐Pragmatic Unit Testing in C# with NUnit(虽然我假设是C#)。它对于教授单元测试的基础非常有用,为工作提供了坚实的基础。

答案 6 :(得分:0)

几年来,我意识到并且在编写单元测试时涉足过。让我真正参与单元测试的是当我开始研究具有令人印象深刻的测试覆盖率的开源项目时。让我印象深刻的是,我编写软件的方式是“在历史的错误方面”。

您提到了许多广告功能让您兴奋的工具,并且想知道如何将它们组合在一起。我认为来自Addison-Wesley(http://xunitpatterns.com/)的“xUnit测试模式”很好地解决了这些问题。这本书让我可以把我过去读到的所有工具和技术集中在一起。

本书可以更好地为那些欣赏其他书籍的读者服务,例如“四人帮”的设计模式,重构和重构模式。这些书也很棒,虽然它们在我阅读之后没有如此直接地改变我的编码方式。 XUnit测试模式的演示虽然反映了书籍的风格。它们起初很难阅读,因为它们倾向于在任意方向上交叉参考章节。我认为它们非常坚固。

GoF提出了模式的类别 - 创造,结构和行为。这些类别用作关联和对比所解释的模式的方式。通过将测试设计模式与单元测试的典型寿命相关联,XUnit测试模式还将一系列可用于单元测试的技术编织在一起。相同的步骤也用于关联和对比用于构建单元测试的各种工具。

它将有助于高级视图,并进入实际实施。

我对XUnit测试模式的唯一批评是他们用来批评NUnit的文本数量。 NUnit是一个很好的编程,其作者的功劳NUNit我们在我认为将成为一本经典书籍中如此突出地提到。