我做对了吗?如果不是,我到底要改变什么
很难只从简短的描述说,但我怀疑,不,你不这样做是正确的。注意:我并不是说您正在做的事情行不通或在某种程度上是不好的,但是您没有在做TDD。中间的“ D”表示“被驱动”,测试驱动一切,开发过程,代码,设计,体系结构,一切。
这些测试告诉您写什么,何时写,接下来写什么,何时停止写。他们告诉您设计和架构。(设计和体系结构是通过重构从代码中产生的。)TDD与测试无关。它甚至不是要先编写测试:TDD是要让测试驱动您,先编写测试只是这样做的必要先决条件。
不管您是实际写下代码还是充分充实代码,这都是无关紧要的:您正在脑海中编写(骨架)代码,然后为该代码编写测试。那不是TDD。
放弃这种习惯很难。真的,真的很难。对于有经验的程序员而言,这似乎特别困难。
Keith Braithwaite创建了一个演习,他将其称为TDD,就好像您是故意的那样。它包含一组您必须严格遵守的规则(基于Bob Martin叔叔的TDD的三个规则,但更为严格),这些规则旨在引导您更加严格地应用TDD。它最适合与结对编程(这样结对可以确保您没有违反规则)和一名讲师一起使用。
规则是:
- 准确地编写一个新测试,这似乎是可以解决问题的最小测试
- 看到它失败了;编译失败计为失败
- 通过编写您可以在test方法中使用的最少实现代码,使(1)通过测试。
- 重构以消除重复,否则可以根据需要改进设计。严格使用以下举动:
- 您需要一个新方法-等待重构时间,然后…通过执行以下方法之一来创建新的(非测试)方法,并且没有其他方法:
- 首选:对根据(3)创建的实现代码执行Extract Method来在测试类中创建新方法,或者
- 如果您必须:将(3)中的实现代码移至现有的实现方法中
- 您想要一个新类-等待重构时间,然后...创建非测试类以提供Move方法的目的地,而没有其他原因
- 通过执行Move方法,用方法填充实现类,而没有其他方法
通常,这将导致与通常使用的“伪TDD方法”截然不同的“伪TDD方法”,即“在脑海中想象设计应该是什么,然后编写测试以迫使该设计,实施您已经设想的设计,然后再编写您的设计测试”。
当一群人使用伪TDD来实现井字游戏之类的东西时,他们通常最终会得到非常相似的设计,涉及某种类型的Board
3×3数组Integer
。至少有一部分程序员实际上会编写此类而不进行任何测试,因为他们“知道自己将需要它”或“需要一些东西来针对其编写测试”。但是,当您强迫同一个小组按照您的意思来应用TDD时,他们往往最终会得到各种各样的非常不同的设计,通常甚至不使用任何与TDM类似的东西Board
。
有什么方法可以确定您编写的测试是否足够?
当它们涵盖了所有业务需求时。测试是系统要求的编码。
是针对非常简单的功能(相当于1 + 1 = 2)编写测试的好习惯吗?
再次,您将其倒退:您无需编写功能测试。您编写测试功能。如果通过测试的功能证明是微不足道的,那就太好了!您只满足系统要求,甚至不需要为此而努力!
更改功能并相应地测试需求是否有所变化是否很好?
不,反之亦然。如果需求发生变化,则可以更改与该需求相对应的测试,观察其失败,然后更改代码以使其通过。测试始终是第一位的。
很难做到这一点。您需要数十甚至数百小时的深思熟虑的练习才能建立某种“肌肉记忆”,以便在截止日期迫在眉睫且您承受压力时,甚至不必考虑它,这成为最快,最自然的工作方式。