BDD工具Cucumber学习记录

栏目: 编程工具 · 发布时间: 6年前

内容简介:首先,我们需要先创建一个新目录并且初始化一个Node工程,如下:然后,添加

一、前言

BDD(Behavior Driven Development) 是一种有效的软件开发与测试方法,它能够清晰化地描述应用程序的行为,用于在业务方、开发者与测试人员之间明确业务需求,并且为更好地自动化测试提供指导。 Cucumber 是广泛使用的一个 BDD 工具,支持多种语言,本文则基于 JS 版的 Cucumber 学习进行总结和记录。

二、如何创建一个Cucumber项目?

首先,我们需要先创建一个新目录并且初始化一个Node工程,如下:

$ mkdir learn-cucumber
$ cd learn-cucumber
$ npm init --yes

然后,添加 Cucumber 作为开发依赖,即:

$ npm i cucumber -D

然后修改 package.json 指定下 test script:

{
    // ...
    "scripts": {
        "test": "cucumber-js"
    }
    // ...
}

此后,我们还需要创建一些目录结构,一个 cucumber 项目需要拥有如下的目录和文件:

  • features 目录
  • features/step_definitions 目录,并在此目录下创建 stepdefs.js ,内容如下:
const assert = require('assert')
const { Given, When, Then } = require('cucumber')
  • 在项目根目录下创建 cucumber.js ,其内容为:
module.exports = {
    default: `--format-options '{"snippetInterface": "synchronous"}'`
}

所以,现在我们的目录结构看起来是这样子的:

+-- learn-cucumber
  +-- features
  |   +-- step_definitions 
  |       |__ stepdefs.js
  |__ cucumber.js

三、Cucumber

1、Cucumber描述文档

当采用 BDD 时,我们需要编写描述文档示例来明确软件的功能,那么在描述文档中,会有多个示例来描述一个特性,而一个示例则称之为一个 场景(Scenario) 。描述文档放置于 feature 目录,并以 .feature 作为文件扩展名

现在,我们以实现”判断周日不是周五“这个Feature为例,可写出如下的描述文档:

Feature: Is it Friday yet?
    Everybody wants to know when it's Friday

    Scenario: Sunday isn't Friday
        Given today is Sunday
        When I ask whether it's Friday yet
        Then I should be told "Nope"

可见,这么一个文件,其构成为:

  • Feature: <feature_name> :特性以及特性名称,通常建议是使用和文件名相似的名称作为特性名称
  • Feature描述 :第二行起的这一段内容是对特性进行描述的,它是一个简短的说明, Cucumber 不会执行这段内容,所以这段内容只是作为文档之用的
  • Scenario: <scenario_desc>场景 描述,即明确地对软件行为做说明
    • GivenGWT(Given/When/Then) 是典型的BDD描述格式。 Given 描述场景的前提条件、初始状态,通常是现在完成时
    • When :表明采取某个动作或者发生了某个事件,是个动词,采用一般现在时
    • Then :用 should be 来描述一种期望的结果

2、编写测试逻辑

现在,我们可以执行如下命令来跑一下 Cucumber

$ npm test

我们会发现执行结果为:

UUU

Warnings:

1) Scenario: Sunday isn't Friday # features/is_it_friday_yet.feature:4
   ? Given today is Sunday
       Undefined. Implement with the following snippet:

         Given('today is Sunday', function () {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });
       
   ? When I ask whether it's Friday yet
       Undefined. Implement with the following snippet:

         When('I ask whether it\'s Friday yet', function () {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });
       
   ? Then I should be told "Nope"
       Undefined. Implement with the following snippet:

         Then('I should be told {string}', function (string) {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });
       

1 scenario (1 undefined)
3 steps (3 undefined)
0m00.000s

这是因为,我们只编写了描述文档,但是并没有指定自动化测试的逻辑,为了能够让 Cucumber 进行自动化测试,我们则还需要根据描述文档编写测试逻辑。测试逻辑可编写在 features/step_definitions/stepdefs.js 里,我们可以简单地复制以上提示的内容,然后 stepdefs.js 看起来便如下所示:

const assert = require('assert')
const { Given, When, Then } = require('cucumber')

Given('today is Sunday', function() {
    return 'pending'
})

When('I ask whether it\'s Friday yet', function() {
    return 'pending'
})

Then('I should be told {string}', function(string) {
    return 'pending'
})

这时候,我们再跑一下 npm test ,输出:

P--

Warnings:

1) Scenario: Sunday isn't Friday # features/is_it_friday_yet.feature:4
   ? Given today is Sunday # features/step_definitions/stepdefs.js:4
       Pending
   - When I ask whether it's Friday yet # features/step_definitions/stepdefs.js:8
   - Then I should be told "Nope" # features/step_definitions/stepdefs.js:12

1 scenario (1 pending)
3 steps (1 pending, 2 skipped)
0m00.001s

这时候, Cucumber 会结合描述文档和测试逻辑,找出步骤定义并且执行测试逻辑。但是当前执行的测试结果为 pending ,这说明我们还需要修改下代码,以做一些有意义的事情

3、测试失败时会怎么样?

我们想知道如果 Cucumber 执行测试不成功时会发生什么,那么我们来改一下 stepdefs.js ,使得预期输出结果不是 Nope ,即:

const assert = require('assert')
const { Given, When, Then } = require('cucumber')

function isItFriday(today) {
    // nothing to return
}

Given('today is Sunday', function() {
    this.today = 'Sunday'
})

When('I ask whether it\'s Friday yet', function() {
    this.actualAnswer = isItFriday(this.today)
})

Then('I should be told {string}', function(expectedAnswer) {
    assert.equal(this.actualAnswer, expectedAnswer)
})

因为 isItFriday 没有任何返回值,所以 this.actualAnswer 的指便永远都是 undefined ,那么在 Then 里, expectedAnswer 会在运行时被赋予 Nope 这个值,故下断言的时候,是不能通过断言的。

执行 npm test ,可看到输出如下:

..F

Failures:

1) Scenario: Sunday isn't Friday # features/is_it_friday_yet.feature:4
   ✔ Given today is Sunday # features/step_definitions/stepdefs.js:8
   ✔ When I ask whether it's Friday yet # features/step_definitions/stepdefs.js:12
   ✖ Then I should be told "Nope" # features/step_definitions/stepdefs.js:16
       AssertionError [ERR_ASSERTION]: undefined == 'Nope'
           at World.<anonymous> (/Users/ruphi.liu/Desktop/Lab/learn-cucumber/features/step_definitions/stepdefs.js:17:12)

1 scenario (1 failed)
3 steps (1 failed, 2 passed)
0m00.002s

4、测试成功时会怎么样?

接下来,我们可以再修改 stepdefs.js 里的逻辑,使得测试能够通过,我们只需要修改 isItFriday() 函数便可,即:

function isItFriday(today) {
    return today === 'Friday' ? 'TGIF' : 'Nope'
}

再次 npm test ,输出:

...

1 scenario (1 passed)
3 steps (3 passed)
0m00.001s

很好,Nice~

5、变量和例子

有时候,我们需要测试多个场景,这些场景可能只是输入和预期输出不同,如果要为此编写多个场景,那么太麻烦了!这种情况下,我们就可以使用 变量例子 功能。仍然拿之前的例子,假设我们现在要判断 周五周日 或者 周XX ,那么我们可以将我们的描述文档改为:

Feature: Is it Friday yet?
    Everybody wants to know when it's Friday

    Scenario: Sunday isn't Friday
        Given today is "<day>"
        When I ask whether it's Friday yet
        Then I should be told "<answer>"
    
    Examples:
        | day           | answer  |
        | Friday        | TGIF    |
        | Sunday        | Nope    |
        | anything else | Nope    |

其中, "<day>""<answer>" 就是变量,而 Examples: 就是例子,例子其实就是对变量的枚举,当执行时, Cucumber 会读入例子中的每一行值,然后传入到测试脚本里执行。因此,我们还需要修改 stepdefs.js ,如下:

const assert = require('assert')
const { Given, When, Then } = require('cucumber')

function isItFriday(today) {
    return today === 'Friday' ? 'TGIF' : 'Nope'
}

Given('today is {string}', function(givenDay) {
    this.today = givenDay
})

When('I ask whether it\'s Friday yet', function() {
    this.actualAnswer = isItFriday(this.today)
})

Then('I should be told {string}', function(expectedAnswer) {
    assert.equal(this.actualAnswer, expectedAnswer)
})

最后执行 npm test ,得到:

.........

3 scenarios (3 passed)
9 steps (9 passed)
0m00.002s

以上就是 Cucumber 基本的使用方法,而具体应用到业务中时,我们还可以抽取公共逻辑、写更模块化的测试逻辑脚本

参考


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Open Data Structures

Open Data Structures

Pat Morin / AU Press / 2013-6 / USD 29.66

Offered as an introduction to the field of data structures and algorithms, Open Data Structures covers the implementation and analysis of data structures for sequences (lists), queues, priority queues......一起来看看 《Open Data Structures》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具