BDD 工具 Cucumber 十周岁:创建者 Aslak Hellesøy 访谈

  • Jan Stenberg
  • 谢丽

2018 年 5 月 10 日

话题:语言 & 开发架构

看新闻很累?看技术新闻更累?试试下载 InfoQ 手机客户端,每天上下班路上听新闻,有趣还有料!

Cucumber的创建是为了应对不明确的需求和误解,供项目团队的非技术成员和技术成员使用,但是,于 2008 年创建 Cucumber 的Aslak Hellesøy几年前说过,如果你把 Cucumber 看成一个测试工具,那么你就错了。在接受 InfoQ 的采访时,他谈了自己从事行为驱动开发(BDD)和 Cucumber 相关工作的经历以及他对这个现在已经 10 周岁的工具的未来的思考。

InfoQ:您能简要介绍下 Cucumber 以及它与行为驱动开发(BDD)的关系吗?

Aslak Hellesøy:Cucumber 是一个支持 BDD 的工具,而 BDD 是 TDD(测试驱动开发)的一个变种。借助 BDD,所有的测试都是客户验收测试,这些测试是使用普通的(人类)语言编写的,因此,非技术的干系人也能理解。Cucumber 把需求规格说明书、自动化测试和在线文档合并成了一种格式 Gherkin,这种格式就是普通的英语,然后稍微加了点结构。

(如果做得好)BDD 可以带来返工减少、Bug 减少、代码可维护性提高等好处。为了获得这些好处,你必须花点精力挖掘需求,并设计出可测试的软件。通常,需求挖掘很快就会有回报,而设计可测试的软件往往会是一种长期的回报。BDD 可以帮助团队快速发现错误,让软件开发更快乐、更可持续。

InfoQ:您 10 年前是因为什么创建了 Cucumber?

Hellesøy:在创建 Cucumber 之前 10 年,我一直是一名软件顾问。在我职业生涯的头 5 年(1998 年至 2003 年),我参与的所有项目都有同一个问题:

  • 我经常不知道我是否完全理解了需求
  • 我发现很难建立那样的自信,就是我们正在构建的东西可以正常运行
  • 我害怕变更现有的代码,不知道会对哪里造成破坏
  • 我们总是延期

在我创建 Cucumber 之前 5 年(2003 年),我加入了三个部分重叠的社区,向现在我们称之为 BDD 的开发方法贡献了大量的想法。在这 5 年里,我有机会和一些真正高效的团队合作,这在我职业生涯初期是不曾遇到的。我们交付,我们自信,我们乐在其中。

第一个社区是 XP 社区,也就是 TDD 产生的地方。由 Ward Cunningham 创建的 Fit 和由 Robert C. Martin 创建的 Fitnesse 对我也有很大的启发。

第二个社区在 ThoughtWorks 内部,我那时在那里工作。Dan North、Chris Matts、Liz Keogh、Joe Walnes、Paul Hammant 和 Chris Stevenson 正在开发 TDD 的变种,而且更关注语言,他们设法在业务需求和编程之间搭建一座桥梁。

第三个社区是 Ruby 社区,David Chelimsky、Steven Baker 和 Dave Astels 构建了第一款具有重大影响的 BDD 工具 RSpec。

Dan North 和 David Chelimksy 在 RSpec 中实现了对 Given-When-Then 语法早期版本的支持。我喜欢上了可执行的规格说明书这一理念,希望可以更进一步,但是,我感觉自己受到 RSpec 设计决策的限制,它的关注点更底层。

我把 RSpec 的 Given-When-Then 解析器提取到一个单独的库里,开始大幅地改进,让它更友好,比如,有用的错误信息、打印代码段、为输出添加颜色、扩展语法、提升速度等等。

我的妻子建议我叫它 Cucumber(没有特别的原因),它的名字就是那样来的。我还决定给 Given-When-Then 语法起个名,从这个工具中独立出来。那就是为什么我称之为 Gherkin(腌制过的小黄瓜)。

InfoQ:这些年来,Cucumber 在社区的使用情况怎么样?

Hellesøy:完全超出预期!10 年来,其使用情况一直在稳步增长,用户数每 18 个月翻一番。其增长尚未出现放缓势头。单是在 2017 年,Cucumber 的下载量就有 2000 万次(Java、.NET、Ruby、JavaScript、PHP 和 Python 实现总计)。

第一个增长高潮是在 2008 年到 2011 年间,来自 Ruby on Rails。

第二个高潮是在 2011 年,Matt Wynne 和我出版了The Cucumber Book之后,该书已经卖了将近 2 万册。我们的书把 Cucumber 和 BDD 带给了新用户。产品经理和业务分析人员开始认识到,这是一种可以减少需求误解的方式。Gojko Adzic 的著作Bridging the Communication GapSpecification by Example也帮助推广了这种理念。

我们的书也把 Cucumber 带到了测试社区,他们把它视为一种自动化测试方式。具有讽刺意味的是,这导致人们误认为 BDD 和 Cucumber 是面向测试的,而且只是测试。当 Dan North 提出 BDD 的时候,他的目标是让 TDD 更好用,是了让开发人员更容易理解,TDD 是一项设计和软件开发技术,而不是测试。

但是,我认为,如果你只有一把锤子,那么任何东西都会看上去像钉子。

现如今,Cucumber 已经成为许多组织标准工具集的一部分。有些把它用作 BDD,但大多数只是把它用于“BDD 测试”,不管那意味着什么,它的名字都是“行为驱动开发”。

InfoQ:从创建至今的 10 年中,Cucumber 经历了怎样的发展?

Hellesøy:在 2008 年,Cucumber 的初始 Ruby 版本发布几年之后,更多其他语言的实现也相继推出:

  • Gaspar Nagy 创建了面向.NET 的 SpecFlow
  • Julien Biezemans 创建了面向 JavaScript 和 Node.js 的 Cucumber.js
  • Konstantin Kudryashov 创建了面向 Behat 的 PHP
  • 我创建了面向 Java 和其他 JVM 语言的 Cucumber-JVM

现如今,对于每一种主要的编程语言(也有许多面向非主流语言的),都有一种 Cucumber 实现。这些实现中的大多数都和最初的 Ruby 实现十分类似,但是,由于维护这些实现的团队彼此独立地工作,所以它们也有一点不同。这总的来说是一个好事;这样会有更多创新。那是一种很棒的共生关系。我们复制彼此的想法。下面是过去几年中新增的部分最重要的特性:

  • Cucumber 表达式——正则表达式的一种替代方案,比前者更友好
  • 标签表达式——一种面向 Gherkin 标签的布尔查询语言,简化执行场景选择
  • Suites(目前仅限于 Behat)——更容易在不同的配置下运行同一个场景(通过 UI 或在后台)
  • IDE 集成,包括 IDEA、IntelliJ 和 Visual Studio

不同实现的差异推动了创新,但也提出了一些挑战。每一种实现和文档的维护都有大量的重复工作。为了解决这个问题,我们很快将发布一个新的网站,它将提供一个统一的地方记录所有正式的 Cucumber 实现。这可以鼓励贡献者把他们的实现集中在一起,让它们更加一致。10 年之后的今天,我们不再需要早期的这种差异和创新——我们现在更需要的是一致性和维护工作的可持续性。

近日,Cucumber.js 团队的 Charlie Rudolph 使用 Go 编写了一个试验性的共享二进制文件,可以用作所有 Cucumber 实现的基础。这有可能简化所有的实现,这意味着我们可以为我们的用户提供更好的产品。

最后,我们计划对 Gherkin 语言本身做些修改,让它更符合 BDD 这些年的发展。我们会确保它向后兼容——我可不想被邮件轰炸!

InfoQ:Cucumber 和 BDD 是什么关系?

Hellesøy:在过去的 10 年里,我自己(以及我的 Cucumber/BDD 伙伴)的 BDD 方法已经发生了很大的变化,这影响到了 Cucumber。有时候,我们对 Cucumber 做了修改,那会改变人们的实践。Cucumber 和 BDD 密不可分,我这里有几个例子。

Behat 项目的 Konstantin 几年前向我介绍了一项新的 BDD 技术,他称之为“实例建模(Modeling By Example)”。思路很简单,就是从部分描述预期行为的几个场景入手。我知道声明式场景(没提供技术细节)比命令式场景(有大量的 UI 细节)好有一阵子了。在他向我展示之前,我没考虑过的是,这同时也让你选择一个不同的开发起点。

之前,我总是从 UI 开始。Konstantin 让我知道,场景也可以用于推动领域逻辑的开发——在 UI 背后,协议层(如 HTTP)之下。这让你可以在同一个进程中运行 Cucumber 和你正在开发的系统。这些测试速度极快,通常是毫秒级的,对生产力有深远的影响。它让你可以非常快速地向稳定的领域模型迭代。

这是着手开发 UI(或者协议层,如 HTTP)的更好时间。因为这些场景不受实现细节的影响,我们可以使用同样的场景(借助不同的自动化代码)推动 UI 或协议层的开发。

如果你只需要告诉 Cucumber 把每个场景运行两次,那么工作流程会大大简化——一次在后台(用可靠性换速度),一次通过 UI(用速度换可靠性)。Konstantin 向 Behat 添加了一个特别的特性“Suites”,这也是我希望在其他 Cucumber 实现中添加的东西。所以,这是 BDD 实践改变对工具产生影响的一种方式。

“实例映射(Example Mapping)”是最近出现的另外一种可能影响 Cucumber 的 BDD 实践。这是我同事 Matt Wynne 提出的一种分析技术。实例映射是一种简洁的协作技术,把用户故事分解成稍后可以变成场景的实例。现如今,我都是先做实例映射,我甚至都没有考虑过编写一个 Cucumber 场景。它已经从根本上改变了我们团队(以及我们培训过的数以百计的团队)的需求分析和测试设计方法。

实例映射按规则把实例分组。由于 Gherkin 没有一个规则结构,当你尝试把一个实例映射“翻译”成 Gherkin 语法时,这会导致一点阻抗失谐。因此,我们计划在 Gherkin 中增加关键词“Rule”,并把“Example”作为“Scenario”的同义词。

InfoQ:您是一名 BDD 及 Cucumber 专家。这些年,您针对这个工具所做的工作有变化吗?

Hellesøy:当然。其中有件事,我一直念念不忘,就是测试速度,在过去的几年中,这方面已经有了长足的进步。

Jakob Nielsen 和 Mihaly Csikszentmihalyi 的研究表明,对于大多数人而言,等待反馈的时间超过 10 秒,他们就很难继续专注于手头的工作。UX 设计人员知道这一点——这就是为什么当事情需要花点时间时会有进度条和旋转指针。为程序员开发工具的人们似乎还没有意识到这一点。

一个需要等待 1 到 5 秒就可以得到测试反馈的程序员,和需要等待 30 秒的程序员,其生产力会有显著的不同。在 1 到 5 秒内,你可以保持非常高效的状态,持续几个小时。如果你总是被打断,就不会出现那种情况。我们已经非常习惯于缓慢的反馈,我们已经预料到,并采取变通措施,而不是解决这个问题。测试金字塔就是这样的一种变通方案。传统观点告诉我们,通过 UI 进行的全栈测试缓慢而脆弱。因此,我们较少做缓慢的“不稳定测试(flaky test)”,而更多地做快速的一致性测试。

解决这个问题的更好方法是让缓慢的测试变快,让不稳定的测试变稳定。可靠性和速度,何乐而不为呢?

Nat Pryce 和 Josh Chisholm 各自独立地研究出了让全栈测试在亚秒级完成的方法,他们移除了所有的 I/O,并让所有的东西都在进程内运行。以前,我们只知道域级测试是这样做的。例如,如果你编写一个有 DOM UI(如 React)的 Node.js 应用,你可以使用 Cucumber-Electron 在一个 Node.js 进程中运行客户端和服务器,根本没有 I/O。每秒执行成百上千的全栈测试。如果速度那么快,就没有人介意冰淇淋甜筒测试了。

降低脆弱性、提升可维护性的方法也变得越来越流行。Screenplay 是其中的一种方式,感谢 Antony Marcano、Andy Palmer、John Ferguson Smart 和 Jan Molak。

InfoQ:社区内有人使用 Cucumber 和 BDD 之外的工具实现同样的目标吗?

Hellesøy:那取决于目标是什么。老实说,大多数使用 Cucumber 的人都不是把它用于 BDD。他们把它用于测试,后来编写测试。如果你的工作流程是那样的,那么 Cucumber 与其他的测试工具相比并没有什么明显的优势。除用户外,领域专家或产品经理会使用它阅读 Gherkin 文档,通常,我会建议使用一种典型的 xUnit 工具来代替(JUnit、RSpec、NUnit、Mocha 等)。

我一般都是混着用:如果是希望从非技术干系人那里获得反馈,我就会使用 Cucumber;如果是希望从技术干系人那里获得与业务需求没有直接关系的反馈,我就会使用 xUnit。

Cucumber 非常适合验证假设、发现不确定性、对要构建的东西建立一个共同的理解。有几种替代的方案和 Cucumber 有相同的目标,但远不及你能找到的传统测试工具的替代方案多。我不不确定其中哪一种最受欢迎,但是,Concordion、Robot 框架、JBehave 和 Fitnesse 与 Cucumber 最为相似。

InfoQ:Cucumber 和 BDD 未来会怎样发展?

Hellesøy:Cucumber 已经成长为一个有许多实现的大型生态系统。用户数庞大(几十万到几百万),而经常贡献者的数量相对较少(约 10 几个),这就是说,我们要不断地减少工作量或者扩大团队规模。一个共享的二进制文件可能可以减少部分工作量,但现在这样说还太早。

分布式执行和并行执行是人们要求比较多的特性。对于这一点,有些变通方案和第三方工具,但是 Cucumber 内没有提供原生的特性。我们希望加入这个特性。我们也希望改进报告工具。

至于 BDD 实践,我认为,作为一个社区,我们能做的最重要的事情是坚持对用户进行 BDD 培训。有些书可供阅读,但我认为,我们需要人们更容易获得、更易于理解的教育资料。目前,我们花了大量的精力教人们实例映射——我们已经看到有团队从中获得了很大的好处,甚至都没有使用 Cucumber。

我们还需要把用于快速测试的模式和技术写成文档,尤其是在分布式架构中,如微服务和无服务器架构。像端口、适配器和契约测试等模式都不是主流,我认为,它们可以解决在那些环境中使用 BDD 时面临的其中许多问题。

InfoQ:您和您的同事已经围绕 Cucumber 创立了一家公司。从那个角度讲,您对未来有什么看法?

Hellesøy:我们在 2014 年成立了 Cucumber 有限公司,从那时开始,我们的主要收入流就一直是培训。这些年来,我们构建了一个 Cucumber 协作工具,名为Cucumber Pro。这个工具可以发布 Gherkin 文档及其结果,让人们可以在那些文档上开展协作。当我们意识到客户需要的是不同的东西时,我们扔掉了第一个,从头开始。

早期,我们决定成立一家自力更生的公司,从第一天开始就没有任何外部投资。如今,我们有 10 名员工,有大约 10 个合伙人帮助我们在全世界开展培训。

我们没有办公室,因此,我们每天通过视频会议见面。在我们中间,从事 Cucumber Pro 开发的使用远程群体编程,而其他人则访问客户提供培训。我们每两个月见一次面,制定策略并聚会。

没有外部投资者让我们对于优先事项有更好的控制,让我们更容易创立我们希望创立的公司,但是,那也意味着,如果我们雇用 10 几名开发人员,我们就无法尽快发展我们的商业产品。这很难,但很有趣!

查看英文原文BDD Tool Cucumber is 10 Years Old: Q&A with its Founder Aslak Hellesøy

语言 & 开发架构