懒人写字通常都是因为看到了某些观点,觉得有话要说不吐不快,比如这次的动力来源是这么一段话——
bdd 的流程是根据自然语言描述的规格生成测试和文档,根据测试来生成代码。自然语言描述的东西能生成测试或文档只有两种可能:你写的根本不是给人类看的自然语言。或者这个过程不是自动化的。cucumber 的情况是它既不够自动化,自然语言也不是给人类读的。
理解BDD
首先说结论,上述观点是有问题的。根据Dan North
的说法:
BDD is a second-generation, outside-in, pull-based, multiple-stakeholder, multiple-scale, high-automation, agile methodology. It describes a cycle of interactions with well-defined outputs, resulting in the delivery of working, tested software that matters.
由于BDD是在TDD的基础上的概念延伸,因此我们需要注意其中和TDD不一样的部分,high-automation
、agile
、wel-defined outputs
等等这些东西显然不是BDD所独有的,所以不是关键。
真正的要害在于outside-in
和multiple-stakeholder
。
所谓multiple-stakeholder
,就是要明确系统为哪些用户服务,提供什么服务和功能,在这个前提下工作才不会出现严重的偏差,这其实也是很多其它敏捷方法的思路。
而强调outside-in
(也被翻译为“由外而内”),正是这个思路的具体做法。
我们知道,软件系统是分层次的
由于软件是分层的,我们的测试也就相应的有了不同层次,BDD要求我们由外而内,就是在明确整个系统对外提供的服务和功能基础上,通过自动化测试进行约束和保证,然后一层一层向下,实现和验证内部的工作细节。
所以综合来看,其实BDD相对于TDD来说,最为重要的着眼点,是在强调自顶而下的设计。
从字面意思——行为驱动开发——也能感受到这个思维方式:我们首先要意识到和明确出,这个“东西”是要“干什么”,然后根据这个认识再来驱动我们的工作。
从TDD到BDD:超越单元测试
测试驱动开发是一个很好的思想,它强调从结果看过程,避免过度设计,建立自动化的测试集以便于对重构进行保护,这些都是很好的理念和实践。
BDD其实并不是对TDD的颠覆,它其实也是在用测试来驱动开发(或者说用结果来推进过程)。只不过,相对于通常的TDD而言,BDD将测试活动的着眼点扩展到行为
这种外部概念,让开发人员从单元测试这种狭窄的概念中解放出来。
一些BDD的开发库和套件都提供了对http client行为的封装,这其实是很有意思的一个现象,要知道,用http client来测试自己的应用,是典型的“外部测试”。多年以前的软件开发中,与之类似的活动一般是有专人(甚至专门的团队)去开发一个模拟器软件,然后用这个模拟器来测试自己的服务,这是一个很重的行为。
在这种背景下,当TDD的概念开始被大家接受的时候,开发人员能够做的事情显然不是直接去开发一个“自己的模拟器”来验证自己的工作——那样成本太高了,他们最直接的反应是——为自己开发的函数编写单元测试。而无论你写多少单元测试,局部正确都不能代表整体正确,相反,这种工作方式会导致整体的错误或者遗漏会在最后才被发现。
从某种角度看,BDD其实是增强版的TDD,它补充和完善了TDD
文档的进化
上述讨论中有一个问题,整体的错误或者遗漏无疑是非常大的损失,但这显然不可能是一个新问题,过去我们又是怎么做的呢?
答案是文档,大量的、需要反复确认的需求文档。
不用我多说你也能理解,由于没有自动化测试保护,我们不得不用大量有歧义的文档来说明我们的系统要做的事情,这个现象在按月甚至按年开发的软件系统中并不是个问题,当然,如果你要做几个月的需求确认,那么开发需要半年时间也是很合理的。
直到敏捷的思想开始影响软件开发。
程序员们开始用测试保护自己的算法质量,开始学会小步快跑,这时,项目本身的周期势必缩短,而那些上层的、外部的因素渐渐成为了瓶颈——我们没有时间写那些复杂的需求文档,我们需要让文档“活”起来,让它可以在与客户(这时候stakeholder
这个词跳了出来)交流中演化,并不断地用它约束和修正我们的工作,于是我们发现,这个文档变成了脚本,变成了软件的模拟客户端。
从这个角度看,本文最初引用的那个网友观点其实也不完全错误,BDD也要求自动化,只不过,这是TDD早就要求的内容,不算BDD的核心。
如果你这时回头再看TDD的思想,其实它没变,只是把手伸长了。
顺便说一句,自动化是非常重要的思想,这些年各种“代码即xxx”的说法非常多,这些可不光是工具厂商的广告 :-P
关于自然语言
网友观点中提到了自然语言的问题,他把这个看得很重,但是这其实是个“延伸话题”,根本不是重点。
道理很简单,前面已经说过,要保证软件系统运行正常,首先要“做正确的事”,这只有客户(stakeholder
)才能评判,而要让他们“入局”,首先要能沟通才行,所谓”自然语言“,只是为了”让多方能够沟通“这一目标的副产品。
理解了这一点,我们就不用纠结,如果用户能看懂基本的“if else
”,那么我们也不必非要写“如果......那么”,而相应的,如果用户阅读英语有困难,那么使用中文写清楚我们的业务就是必须的——或者你给用户简单培训一下词汇表也行。