TDD的另一个问题或弱点是:总有许多TDD的坏例子。许多提倡TDD的网站都提供了样例代码,基本是像这样的:你有一个需要测试新类的单元测试。单元测试通常对要测试的类设置一个属性并试着复述这个属性。有了合理大小的任何类,可以快速漂亮地对单元测试进行设置。但是,我们稍微往后退点,我们究竟在测试什么?好吧,我们在测试代码是否能够接受一个值以及检索该值的可能性的场景中,一切都是平等的。这归结起来是测试编译器或翻译器,因为作为一名开发人员,你所写的实现这个行为的代码的数量(以及其复杂度)接近零。换句话说,这样的测试只提供一个虚假的安全感,因为到后你什么也没测到。反对其的理由是:随着时间的推移,这种getter/setter代码或许会变得更复杂,接着单元测试代码变得能帮助避免回归。但是我们的经验表明,a)当规模大得能使起初的努力变得有价值时几乎不会出现这种情况了;b)如果你在对你的代码做如此大的改变,从基本的getter/setter配对变为更复杂的计算,那么很可能你希望你的单元测试中断。对于单元测试来说,这个故事的寓意是什么呢?我们要完全放弃他们吗?不,但是我们认为这需要考虑对于单元测试你真正想要的是什么。的单元测试覆盖对我们来说意味着我们在浪费精力。换个角度,TDD作为一个概念并不坏,感觉它迫使你思考你真正需要建立什么以及你怎么让它被接受(测试它)。但是我们认为它的基本方法给了开发人员太多“权力”。给人的大印象是:开发人员(在时间压力下)试图创建通过测试的“东西”,这样而已。因此,如果测试错了,那么并不是开发人员的错。我们觉得它低估了一名的开发人员的实力并给了任何有代码编译器的人一个定义自己为开发员的机会。这是不对的。
寻找软件可测试性,我们发现了另一个我们不可能接受的问题——生成“可测软件”的方法放在你的架构上的压力。让一个系统“可测”是一件事,但依我们之见,对架构实施严格原则(反转控制,依赖注入或极其严格的层分离)只会大大降低代码的难度;还有很重要的一点:它对系统的目标(即解决问题)没有帮助。对于高难度的系统,这样的方法或许是可防御的,甚至是非常好的。但是在这个我们居住的快节奏不断变化的世界里,我们诸多问题中小的一个是:如果我们已经知道两年的时间整个业务系统都将被废弃,那一个软件是否能维持十年。我们甚至会认为两年的时间关于一个好架构该是什么样的见解将会大大地改变。那么还这么麻烦干嘛?我们应该集中精力到有用的(好是在前所未有的短时间内上市的)软件上。
因此我们的结论是:应该抱着怀疑的态度来看待任何需要额外重新策划基本可行可靠的架构的测试方法。因此,我们不使用要求我们的代码能够在没有数据库的情况下工作的单元测试。我们不使用复杂的“mocking”,我们不花时间使我们的类和对象彼此独立。我们知道这并不会生成“正确的”代码。但是,我们并不介意。如果明天我们找到一个更好的方法,我们将改变我们的代码模板且只需重新生成我们的app代码。所以我们对首先创建正确的架构并没有过度担心——事实上我们已经改了它两次了,但是那是另一个blog。
那么这是不是意味着测试驱动开发的结束?完全不是。也有你可以用单元测试测试地很好的东西。另外,还有一个新的我们已调查过的衍生,它表明了我们想测试其他领域:行为驱动开发(BDD)的承诺。BDD有着和TDD一样的开端,某种意义上讲,开发流程的开始是对(将来的app会需要通过以被接受的)测试的定义。但是BDD更适合这个任务,因为似乎比起它该如何被创建,它更注重一个系统的功能。因此,对TDD很少有什么不好的评价。一方面,它通过使用特定语言指定测试(或验收标准,如果你愿意的话)提供了一个连接用户和开发人员的方法。这种语言,Gherkin(github.com/cucumber/cucumber/wiki/Gherkin),是如此简单以至学习曲线相当平缓,表明每个人都可以在前所未有短的时间内学习理解它。写正确的Gherkin需要更多时间。对我们来说,其主要优势是Gherkin提供一个方法让开发人员可以在可理解的水平上交流一个系统的功能。其主要缺点是你终要用许多Gherkin完整地描述一个系统的合理大小。
后,这是我们关于大多数这些“方法”(包括UML在内)的主要评论。如果你有一个不仅仅是一个简单的计算器的系统,那没有足够强大的建模语言可以以这样一种你可以理解并比看着屏幕和实现这些屏幕的代码更快地描述它的方式来描述一个全面完整的系统。
所以,调查继续……
版权声明:本文出自 SPASVO泽众软件测试网:http://www.spasvo.com/news/html/2015430104822.html
原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。