Language agnostic 测试驱动设计-哪里出了问题?

Language agnostic 测试驱动设计-哪里出了问题?,language-agnostic,refactoring,tdd,Language Agnostic,Refactoring,Tdd,我正在家里玩一个玩具项目,以便更好地理解测试驱动设计。起初,事情似乎进展顺利,我陷入了测试失败、编写代码、通过测试的困境 然后我加入了一个测试,意识到我目前的结构会很困难,而且我应该拆分一个有太多责任的特定类。为下一次测试增加更多的责任显然是错误的。我决定搁置这个测试,重构我所拥有的。这就是事情开始出错的地方 如果不同时破坏大量的测试,重构是很困难的,然后唯一的选择似乎是进行许多更改,希望我最终回到测试再次通过的地方。这些测试本身是有效的,我只是在重构时必须破坏几乎所有的测试。重构(我仍然不太满

我正在家里玩一个玩具项目,以便更好地理解测试驱动设计。起初,事情似乎进展顺利,我陷入了测试失败、编写代码、通过测试的困境

然后我加入了一个测试,意识到我目前的结构会很困难,而且我应该拆分一个有太多责任的特定类。为下一次测试增加更多的责任显然是错误的。我决定搁置这个测试,重构我所拥有的。这就是事情开始出错的地方

如果不同时破坏大量的测试,重构是很困难的,然后唯一的选择似乎是进行许多更改,希望我最终回到测试再次通过的地方。这些测试本身是有效的,我只是在重构时必须破坏几乎所有的测试。重构(我仍然不太满意)花了我五六个小时才回到所有通过的测试。这些测试确实帮助了我

感觉好像我脱离了TDD轨道。你认为我做错了什么


由于这主要是一个学习练习,我正在考虑回滚所有重构,并尝试以更好的方式再次向前推进。

也许您测试的a级别太低了。很难说没有看到您的代码,但通常我会从头到脚测试一个特性,并确保我预期的所有行为都发生了。单独测试每一个方法将为您创建一个测试web


您可以使用NCover和DotCover等工具来检查是否遗漏了任何代码路径。

拆分类时可能速度过快。测试的步骤如下所示:

  • 创建新类
  • 将该类的实例作为私有数据成员
  • 到新班级,一个接一个
  • 编译并测试每个字段
  • 到新的班级,一个接一个,每个班级都要进行测试
这样,在重构类时就不会破坏大量的测试,并且可以依靠这些测试来确保在整个类拆分过程中没有破坏任何东西


另外,确保您正在测试行为,而不是实现

唯一的“错误”是在之后添加一个测试。在“true”TTD中,您首先声明实际实现之前的所有测试。我说“真”是因为这通常只是理论。但在实践中,你仍然拥有测试所提供的安全性。

不幸的是,TDD支持者没有充分谈论这一点,这使得人们尝试TDD,然后放弃它

我所做的是我所称的“高级测试”,它包括避免单元测试和专门进行高级测试(我们可以称之为“集成测试”)。它工作得很好,我避免了你提到的(非常重要的)问题。我不久前写了一篇关于它的文章:


祝TDD好运,暂时不要放弃。

我想对被接受的答案发表评论,但我目前的声誉不允许我这样做。这是一个新的答案

TDD表示:

创建失败的测试。编码一点。通过考试


它坚持以微小的步骤进行编码(特别是在开始时)。将TDD视为您为构建程序而执行的连续重构的系统验证。如果你迈出了太大的一步,你的重构就会失去控制。

同样对于TDD,测试用例的回归也是必要的。因此,与覆盖工具(如上所述)的持续集成是必要的。因此,可以很容易地回归小的更改(即重构),并且可以很容易地找到丢失的任何代码路径


我还觉得,如果以前没有编写测试,就不应该浪费时间考虑是否编写测试。测试应该立即编写。

我的测试通常是:构造域模型的某些部分,从(模拟的)用户界面给它一个或两个事件,并通过查询域模型断言结果是什么。我的测试使用与UI层相同的界面,因为我是自顶向下构建的。(其他一些测试只是针对一个特定类的单元测试,以确保正确性)。单元测试是孤立地测试每个方法。TDD在编码实现之前创建单元测试,我称之为“单元测试”的测试仍然是首先编写的。他们只专注于一门课。其他人的范围更大(从模拟GUI事件开始,一直到模拟GUI结果)。我认为他的意思是,他在做了一些工作后添加的测试是为了一个新功能,不适用于现有代码。我打算为下一个功能添加一个测试,当时我意识到如果不进一步膨胀现有类,它将不适合。那是我决定在尝试添加更多功能之前需要重构的时候(更新了问题以希望澄清)。。。是的,设计一个系统,使其能够扩展到不可预见的特性,这始终是一个巨大的挑战。我想这是读书不会让你走得太远的事情之一,而且(大部分)一切都归结于经验。我喜欢学习的承诺。我认为回过头来应用@phillipe的答案是个好主意。-1,因为单元测试非常重要,非常有价值。高级测试告诉您出了什么问题——这也是非常有价值的——但单元测试告诉您出了什么问题。但接下来发生的事情是,单元测试变成了一种负担,因为它们使重构更加耗时。当这种情况发生时,您就不太容易进行重构。那太糟糕了。单元测试只有在你允许的情况下才会成为一种负担。重构实际上是一件我非常自信的事情,有大量的单元测试。是的,你可能会有一段时间的测试失败,但这可以用phillippe描述的方式来避免,或者是你在工作时认为理所当然的事情