BDD是什么

BDD,Behavior Driven Development,行为驱动开发。

如果你不是很了解BDD,可以参考我四年前的一篇文章 说起BDD,你会想到什么 ,其中介绍过BDD的理论和应用。

我们可以这样来概括BDD:

  • BDD采用统一的 领域特定语言(DSL) 来描述业务场景和用户行为,让团队各个不同角色对 业务 需求有一致认识,从而做到更有效的沟通和更 高效的协作
  • BDD的目的不是自动化测试,但是BDD可以有效指导自动化测试,基于BDD的自动化测试相当于维护了一份需求 活文档 ,对项目需求的维护和管理非常有价值。

BDD应用框架之Cucumber

BDD的应用

BDD是为解决下面三个方面的问题而生:

  1. 协作:多个角色在一个团队,如何从一致理解需求开始高效协作?
  2. 语言:不同的角色业务、开发和测试人员分别说自己的语言,如何统一语言,更有效的沟通?
  3. 文档:编写和维护的成本都很高,如何低成本的维护一份有价值的文档?

Cucumber是一款支持BDD的框架,有助于帮助团队解决以上问题。

Cucumber支持用自然语言描述业务场景,需要遵循Given-When-Then的格式,这样就可以容易的对应到自动化测试的3A步骤Arrange-Act-Assert,从而实现业务场景的自动化测试。

Cucumber的理想是将可执行的需求规范、自动化测试和活文档有机的结合,如下图所示:

Cucumber的理想

理想很丰满,现实很骨感。Cucumber在实际应用中的情况又如何呢?

Cucumber的痛点

Cucumber框架实现Web自动化测试包括两个部分:Feature(特性)文件和Step Definition(测试实现),在实际应用中人们普遍感觉到它的复杂。

  • Cucumber特别强调的是协作,Feature文件通常由偏业务的人员来编写,要求遵循Given-When-Then的格式。这种固定的语法对编写人员要求较高,写起来比较费劲,尤其对新人不友好,很多团队反映要写出好的Feature文件特别费时费力。
  • Cucumber支持多种语言实现测试代码,但它本身并不能实现自动化,对于Web自动化测试需要跟其他自动化工具结合,比如Selenium-WebDriver。实现代码不仅复杂,还有着元素定位难、执行时间长、不够稳定的痛点。

Cucumber-js+Selenium WebDriver实现的代码长这样:

Feature定义:

Feature: Google Search
  Scenario: Finding some cheese
    Given I am on the Google search page
    When I search for "Cheese!"
    Then the page title should start with "cheese"

Steps实现

Given('I am on the Google search page', async function () {
    await driver.get('http://www.google.com');
});

When('I search for {string}', async function (searchTerm) {
    const element = await driver.findElement(By.name('q'));
    element.sendKeys(searchTerm, Key.RETURN);
    element.submit();
});

Then('the page title should start with {string}', {timeout: 60 * 1000}, async function (searchTerm) {
    const title = await driver.getTitle();
    const isTitleStartWithCheese = title.toLowerCase().lastIndexOf(`${searchTerm}`, 0) === 0;
    expect(isTitleStartWithCheese).to.equal(true);
});

新一代BDD框架

蓝鲸项目曾经就是用Cucumber+Selenium WebDriver实现的UI层自动化测试,由于上述痛点,大家觉得UI自动化测试越来越难写,我也因此对BDD丧失了信心。

自从遇到了两款新的工具Gauge+Taiko,我又重新对Web系统的实现基于BDD的自动化测试燃起了希望。

Gauge

Gauge 是一款开源的轻量级跨平台自动化测试工具,它的愿景是用更少的代码、更少的维护工作实现更多的自动化测试,有如下特性:

  • 采用Markdown格式,支持用自然语言编写Spec,语法自由,编写工作简单易上手,不管是对业务人员还是技术人员都很友好;写出来的文档格式清晰,很好维护。
  • Gauge本身可以实现对Web页面的访问和控制,支持多种语言,各种API封装的很好,代码实现部分比Selenium要简单很多,尤其对于编程技能不是那么强的QA来讲非常友好,易上手,代码的可读性也更强一些。

Taiko

Taiko 也是一款开源浏览器自动化测试工具,它的特性如下:

Taiko的特性

  • 交互式的录制体验。Taiko提供类似于irb的REPL,直接输入命令,可以看到浏览器执行结果,同时后续还可以把成功执行的命令直接生成JS代码,非常方便。
  • Taiko不仅提供常见UI自动化测试工具那样根据Id、name、CSS、Xpath等方式选择页面元素的功能,还提供智能选择器(Smart selector),支持直接根据显示的文本来定位各种类型的页面元素,同时还有支持上、下、左、右这种根据某个元素的相对方位去定位元素的API,很好的解决UI测试页面元素定位难的问题。
  • Taiko采用隐式的等待(Wait)方式,也可以手动设置超时时间以防有些访问等待时间过长。这种隐式等待相比其他自动化工具需要手动设置等待时间的显式等待方式要更高效、更稳定。
  • 与Gauge的完美结合:Taiko在REPL里执行的浏览器操作步骤,可以通过一个简单的命令直接生产Gauge支持的Step,只需要再去简单的加上step名称就可以,操作及其简单。

Gauge+Taiko的代码长这样:

Spec定义

# Google Search

This is an executable specification file. This file follows markdown syntax. 
Every heading in this file denotes a scenario. 
Every bullet point denotes a step.
To execute this specification, use
    npm test

## Finding some cheese
* Goto Google search page
* Google for "Cheese!"
* Page title starts with "Cheese"

Steps实现

step("Goto Google search page", async function() {
    await goto("www.google.com");
});

step("Google for <query>", async (query) => {
    await write(query);
    await click("Google 搜尋");
});

step("Page title starts with <content>", async (content) => {
    await title().then((pageTitle) =>{
        assert.ok(pageTitle.startsWith(content));
    });
});

总结

协作是人的问题,工具可以起到辅助作用,但是不能解决根本问题,过于严格的工具缺乏灵活性,反而阻碍了高效协作的可能。

Gauge不强调协作,可以作为自动化测试工具独立存在,同时又支持高效协作、支持实现BDD,是一款灵活性更好的框架。它的秘密武器Taiko是一款优秀的Web UI自动化工具,两者的结合堪称完美,让需求规范、自动化测试和活文档的有机结合真正成为可能。

本文只是将Gauge和Taiko跟Cucumber框架从对BDD的角度做简单的对比,更多的关于Gauge和Taiko的高级特性,请参考【延伸阅读】部分相关文章。

延伸阅读

更多精彩洞见,请关注微信公众号:ThoughtWorks洞见

相关文章