转载

从 TDD 到 BDD

从踢弟弟到逼弟弟

自从2015年10月十八届五中全会决定全面放开二胎,一对夫妇可以生育两个孩子。身边不少头胎生了女孩的夫妻积极响应国家号召,生下了第二胎,而且大部分人二胎生的都是男孩,凑得个好字,儿女双全。

但是,有人的地方就有江湖,有江湖的地方就有竞争。许多头胎的孩子,本来颠颠高高兴兴,万千宠爱在一身。突然一天,爸爸妈妈告诉他们,要当哥哥/姐姐了,懵懂的他们还不知道是什么回事。直到弟弟/妹妹降生,全家人注意力迅速转移,哥哥/姐姐们才知道歌里唱的“由来只有新人笑,有谁听到旧人哭”是什么意思。小小年纪开始了体会怨憎会、求不得之苦。

若是二胎是弟弟,自己是女儿身,而又生在那重男轻女之家,那苦真叫作苦过弟弟。老大心理上如不能适应,则有可能对弟弟下手,各种踢弟弟。然而小孩动手不知轻重,踢弟弟容易有伤痕,被大人发现了那可是胆汁送黄莲,苦上加苦。于是,扭曲的小孩另寻方法,改为心理上摧残弟弟,从踢弟弟转为逼弟弟。

国外就有一些小孩,早早就从踢弟弟转为逼弟弟。他们就是

敏捷开发工程师

他们搞了个敏捷宣言

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Customer collaboration over contract negotiation
  • Responding to change over following a plan
  • That is, while there is value in the items on
  • the right, we value the items on the left more.

简单来说是加强沟通,忙尽快出能工作的软件。

目的是为了摆脱过去那种大型项目开发的中因为因循繁琐的流程、维护大量的文档所造成的低效率,从而适应项目小型化,拥抱需求变化,营造一个欢乐开发的海洋。

为了实现其中的第二点,尽快提供工作的软件(Working software),有些小孩又搞了一个敏捷实践,叫做

踢弟弟(TDD Test-Driven Development)

他搞了几个原则

  • write a "single" unit test describing an aspect of the program
  • run the test, which should fail because the program lacks that feature
  • write "just enough" code, the simplest possible, to make the test pass
  • "refactor" the code until it conforms to the simplicity criteria
  • repeat, "accumulating" unit tests over time

概括来说,是先写一小段某个功能的测试代码,测试失败,再写实现代码,测试成功,再迭代下一个功能。

这对于单元测试与开发是很有用的一种实践。因为踢弟弟是要求在写代码之前就要想好怎么测,测什么,这解决了可测性低的问题。另外,踢弟弟还可以提高代码的测试覆盖率,令bug在编码阶段就能被发现。减少上线后发现问题,修复问题的指数级增长成本。

然而,踢弟弟也有它的不足。

  • 它解决的是代码级的验证,但是测试代码与需求的符合问题解决得不是很好,非技术人员、客户看不懂代码,无法评审测试是否符合需求。
  • 测试代码可能写得太大或者太小,令开发人员效率下降。这与测试代码与功能对应不起来有很大关系。

于是,又有一些小孩扩展了踢弟弟,提出了

逼弟弟(BDD Behaviour-Driven Development)

他们发现,如果将自然语言按照一些简单语法组织起来,代码将会非常容易解释与处理。使用这种方法可以让非技术人员、客户可以参与到需求的确认与验收当中。

我们看一下两个例子

Scenario: Refunded items should be returned to stock
  Given a customer bought a black sweater from me
    and I have three black sweaters left in stock.
   When he returns the sweater for a refund
   then I should have four black sweaters in stock.


场景: 微信聊天
假如  手机安装了微信
当  用户打开微信
那么  手机会出现用户的微信聊天界面

以上就是逼弟弟使用的叫做Gherkin的语言,它的理念是使用自然语言来描述功能,而且强调的是使用例子来说明需求功能。是不是跟敏捷开发中的用户故事(User Story)很像?嗯,因为它们都是一个妈生的。

其实只要我们回顾一下敏捷宣言,就会发现,逼弟弟干的事就是解决个体之间互动与客户协作这两个问题。

逼弟弟的需求研讨会(Specification Workshops)

那么,我们使用这种语言,把需求一个个用例子列出来,客户/产品、开发、测试三方一起讨论与确认。

逼弟弟的由外而内的开发模式(Outside-In Development)

然后,开发人员使用BDD工具(JBehave, Cucumber, Behave)去运行、实现测试脚本。再一点点编写实现功能代码,走到所有的功能都运行通过。

由于开发的过程是从最接近用户的UI界面开始,再想到内部设计,因此它称为由外而内的开发模式。如果再加上由内而外的过程,嗯,《开发人员的自我修养》就等着你来写了,你叫史坦尼斯拉夫斯基对吧?

回到Gherkin语言,我们上面提到它需要遵循一定的简单语法

  • Scenario(场景),说明功能的例子
  • Given(假如),构造测试的环境条件
  • When(当),给予的输入,可以是用户,也可以是外部系统,也可以是系统本身定时/条件触发的
  • Then(那么),系统的输出,或者说行为

若干个Given,When,Then构成一个Scenario,若干个Scenario构成一个Feature,若干个Feature最终构成一个系统的完整功能需求。

逼弟弟的不足

由于自然语言的天生缺陷,光用文字总会有一些歧义会产生。例如

冬天能穿多少就穿多少
夏天能穿多少就穿多少

Gherkin语言不能完全解决自然语言的歧义问题,如果有图片,那会很有帮助。然而,现有的Gherkin语言与BDD工具并不支持插入图片。

从 TDD 到 BDD

那你问我资不资瓷,我当然资瓷啊。你们啊,要努力提高姿势水平。国外那Stack Overflow,水平不知道比你们高到哪里去,我跟他们谈笑风生。

支持的办法就是将Gherkin语言与Markdown语法crossover,用Markdown标签来插入图片。

就像这样

场景: 微信聊天
假如  手机安装了微信
当  用户打开微信
那么  手机会出现用户的微信聊天界面
![微信聊天界面](wechat.jpg)

但是由于Markdown不支持图片尺寸定义,图片不能缩放,效果可能就会变成

从 TDD 到 BDD

图片会显得很大,一页都显示不完,体验很差。

有人提出使用 ![微信聊天界面](wechat.jpg =320x) 这种办法,可惜的是,不是所有工具/网站都支持。

又有人提出另外写一个css文件来解决这个问题,但是Stack Overflow上很多人表示,另外维护一个文件很不友好。而且,在逼弟弟这个事情上,让非技术人员去写css更加不切实际。因此,我暂时推荐的解决办法是在Markdown中使用HTML标签<img>。

就像这样

场景: 在搜索框搜索目的地
    假如      用户在手机上登录了手机助手
    当     用户在手机助手上选择导航
    那么      手机助手进入导航页面
#<img src="./Main.jpg" width="240">

效果就会是这样

从 TDD 到 BDD

这里有个tricky的地方,就是html标签前面要用井号注释起来,这样写的好的markdown文件,只要将后缀名从.md改为.feature,就可以使用各种BDD工具运行解释,不影响运行啦。

从 TDD 到 BDD

原文  https://testerhome.com/topics/6804
正文到此结束
Loading...