行为驱动开发由 Dan North 于2003年提出,6年后的伦敦敏捷大会上他给出了一个定义。
BDD是第二代的、由外及内的、基于拉(pull)的、多方利益相关者的(stakeholder)、多种可扩展的、高自动化的敏捷方法。它描述了一个交互循环,可以具有带有良好定义的输出(即工作中交付的结果):已测试过的软件。
上面的定义难于理解,现给出一个通俗的定义。
BDD 的实践者们通过沟通交流,具体的示例和自动化测试帮助他们更好地探索,发现,定义并驱动出人们真正想用的软件。
个人的理解
在接口测试、UI 外面套了一层自然语言。
这个自然语言的作用是让不懂编程的人能在需求上达到一致的理解。
示例
从无到有的驱动开发类
自然语言
'' @math
'' Feature: Simple maths
'' Cucumber 5.x sample:
'' In order to do maths
'' As a developer
'' I want to increment variables
''
'' Scenario: easy maths
'' Given a variable set to 1
'' When I increment the variable by 1
'' Then the variable should contain 2
''
'' @complex @math
'' Scenario Outline: more complex stuff
'' Given a variable set to <var>
'' When I increment the variable by <increment>
'' Then the variable should contain <result>
'' Examples:
'' | var | increment | result |
'' | 100 | 5 | 105 |
'' | 101 | 5 | 106 |
'' | 200 | 6 | 205 |
'' | 1000 | 6 | 2005 |
脚本编写 definitions1.js
''
'' const { Given, When, Then } = require('cucumber');
'' const lib = require('./lib')
'' //// Your step definitions /////
''
'' Given(/^a variable set to (\d+)/, async function (num) {
'' lib.incrementBy(num);
'' });
''
'' Then(/^the variable should contain (\d+)$/, async function (num) {
'' if (lib.variable != parseInt(num)) {
'' throw new Error('Variable should contain ' + num +
'' ' but it contains ' + lib.variable + '.');
'' }
'' });
''
脚本编写 lib.js
''
'' class MathLib {
'' constructor() {
'' this._variable = 0;
'' }
''
'' setTo (number) {
'' this._variable = parseInt(number);
'' }
''
'' incrementBy(number) {
'' this._variable += parseInt(number);
'' }
''
'' get variable() {
'' return this._variable;
'' }
''
'' }
''
'' module.exports = new MathLib();
UI测试类
自然语言
'' # language: zh-CN
'' 功能: Bing搜索
'' 功能:这是一个测试搜索引擎的示例功能
'' 时间:2019-08-08
''
'' @Search
'' 场景: 从 bing 搜索东西并验证
'' 假如浏览到网站 "https://www.bing.com"
'' 当输入关键字 "Cerno"
'' 并且单击 “搜索” 按钮
'' 那么搜索结果应包含 "Cerno"
脚本编写 definitions1.js
''
'' const { Given, When, Then } = require('cucumber');
'' const lib = require('./lib')
'' //// Your step definitions /////
''
'' Given(/^a variable set to (\d+)/, async function (num) {
'' lib.incrementBy(num);
'' });
''
'' Then(/^the variable should contain (\d+)$/, async function (num) {
'' if (lib.variable != parseInt(num)) {
'' throw new Error('Variable should contain ' + num +
'' ' but it contains ' + lib.variable + '.');
'' }
'' });
''
接口测试类
自然语言
~~ @shipperLogin
~~ Feature: Shipper Login
~~ 【GSQ-11】作为**,我想登录 APP,以便登录。
~~ 【描述】
~~ 1.货主端输入手机号、验证码登录。
~~ 2.手机号格式正确且为货主手机号。
~~ 3.验证码正确。
~~ 4.登录成功提示“登录成功”。
~~
~~ Scenario Outline: Post data
~~ * Post to service api "<URL>" with '<data>' and I should get the '<expectval>'
~~ Examples:
~~ | URL | data | expectval |
~~ | http://****/login | { "flowNo":"000005", "term":"0001", "corp":"", "object":{ "phone":"183****8", "verificationCode":"0000", "appName":"shipper" } } | { "errCode": "20005", "errDesc": "登录", "cliFlowNo": "000005", "object": null } |
~~ | http://****/login | { "flowNo":"000005", "term":"0001", "corp":"", "object":{ "phone":"183****5", "verificationCode":"0000", "appName":"shipper" } } | { "errCode": "10001", "errDesc": "请输入正确的手机号", "cliFlowNo": "000005", "object": null } |
脚本编写 definitions1.js
~~ var { Given, When, Then } = require('cucumber');
~~ var got = require('got');
~~ var assert = require('assert');
~~
~~ var jsonFormat = {
~~ headers: { 'Content-Type': 'application/json' },
~~ json: true
~~ };
~~
~~
~~ Given("Post to service api {string} with {string} and I should get the {string}", function (url, data, expectval) {
~~ var option = {
~~ headers: { 'Content-Type': 'application/json', 'Authorization': 'MTIzMDE4NTkyNDM6RUFBQ0FBQUFCTHdJQ' },
~~ json: true,
~~ body: JSON.parse(data)
~~ };
~~ return got.post(url, option).then(function (res) {
~~ var data = res.body;
~~ delete data.svcFlowNo;
~~ var assertdata = JSON.parse(expectval);
~~ return assert.deepEqual(data, assertdata);
~~ });
~~ });
~~