行为驱动的测试

最后编辑了

行为驱动的测试(BDT)定义了以人类可读给定的-Then格式的用户故事。该测试方法通常用作行为驱动的开发的一部分( BDD. )或其他敏捷开发工作。

为了展示BDT的使用率,我们已经实现了基于De-Facto标准输入语言的JavaScript框架 嫩香。本文展示了此框架的使用,可根据要求提供。

输入

地址簿.Feature. 文件描述了预期的行为 地址簿 在创建和填写地址簿时应用程序。它包含两个不同的场景,其中给定,何时何地步骤。

地址簿.Feature.

特征: 填写地址簿

设想: 创建的初始状态

给予 没有现有的地址簿

什么时候 我创建一个新的地址本

然后 没有参赛作品应该存在

设想: 添加首次条目后的状态

给予 一个新创建的地址

什么时候 进入第一个人

然后 应该存在一个条目

上面的功能文件放在内部 tst_addressbook. 行为驱动开发测试套件的测试用例 Suite_bdd.。作为测试案例实施的准备下列 squRunner. 执行将生成一个测试脚本骨架:

$ FEATURE=addressbook squishrunner --testsuite suite_bdd --testcase tst_generator

测试骨架

test.js. 骨架看起来像这样:

source(findFile("scripts", "Feature.js"));

var feature = new Feature("addressbook.feature");

// Scenario 1
var scenario1 = feature.addScenario("创建的初始状态");

scenario1.给予("没有现有的地址簿", function () {
    test.log("Implement me!");
})

scenario1.什么时候("我创建一个新的地址本", function () {
    test.log("Implement me!");
})

scenario1.然后("没有参赛作品应该存在", function () {
    test.log("Implement me!");
})

// Scenario 2
var scenario2 = feature.addScenario("添加首次条目后的状态");

scenario2.给予("一个新创建的地址", function () {
    test.log("Implement me!");
})

scenario2.什么时候("进入第一个人", function () {
    test.log("Implement me!");
})

scenario2.然后("应该存在一个条目", function () {
    test.log("Implement me!");
})

function main() {
   feature.execute();
}

test.log()语句表示仍需要填充控制要测试应用程序的呼叫的功能。

测试实施

通过使用 应用 便利级函数的实现是每增加1-3行的问题:

source(findFile("scripts", "Feature.js"));
source(findFile("scripts", "Application.js"));

var feature = new Feature("addressbook.feature");

// Scenario 1
var scenario1 = feature.addScenario("创建的初始状态");

scenario1.给予("没有现有的地址簿", function () {
    this.scenario.application = new 应用();
    this.scenario.application.launch();
})

scenario1.什么时候("我创建一个新的地址本", function () {
    this.scenario.application.createAddressbook();
})

scenario1.然后("没有参赛作品应该存在", function () {
    test.compare(this.scenario.application.countEntries(), 0);
})

// Scenario 2
var scenario2 = feature.addScenario("添加首次条目后的状态");

scenario2.给予("一个新创建的地址", function () {
    this.scenario.application = new 应用();
    this.scenario.application.launch();
    this.scenario.application.createAddressbook();
})

scenario2.什么时候("进入第一个人", function () {
    this.scenario.application.addDummyEntry();
})

scenario2.然后("应该存在一个条目", function () {
    test.compare(this.scenario.application.countEntries(), 1);
})

function main() {
   feature.execute();
}

帮手对象

之前所提 应用 基于以蜂鸣器创建的录制,为方便而创建了类。围绕正在测试的应用程序缠绕,可以在测试用例之间共享。函数application.launch(),createAdressbook(),addDummyEntry()和countentries()如下所定义:

import * as names from 'names.js'
function 应用() {
    this.launch = function() {
        startApplication("AddressBook.class");
    }
    this.createAddressbook = function() {
        activateItem(waitForObjectItem(names.AddressBook_JMenuBar,
				                   "File"));
        activateItem(waitForObjectItem(names.File_JMenu, "New..."));
    }
    this.addDummyEntry = function() {
        activateItem(waitForObjectItem(
                     names.AddressBook_JMenuBar, "Edit"));
        activateItem(waitForObjectItem(names.Edit_JMenu, "Add..."));
        type(waitForObject(names.AddressBook_AddForename_JTextField),
                           "Mike");
        type(waitForObject(names.AddressBook_AddForename_JTextField),
                           "<Tab>");
        type(waitForObject(names.AddressBook_AddSurname_JTextField),
                           "Meyers");
        type(waitForObject(names.AddressBook_AddSurname_JTextField),
                           "<Tab>");
        type(waitForObject(names.AddressBook_AddEmail_JTextField),
                           "mike@example.com");
        type(waitForObject(names.AddressBook_AddEmail_JTextField),
                           "<Tab>");
        type(waitForObject(names.AddressBook_AddPhone_JTextField),
                           "0123/456789");
        clickButton(waitForObject(names.AddressBook_AddOK_JButton));
    }
    this.countEntries = function() {
        return findObject(names.AddressBook_JTable).rowcount;
    }
}

执行

现在,可以执行行为驱动的测试。它可以从鳞片IDE或命令行完成:

$ squishrunner --testsuite suite_bdd --testcase tst_addressbook

以下是运行的日志:

START_TEST_CASE Start 'tst_addressbook'         Test Case 'tst_addressbook' started
LOG            	shared/scripts/Feature.js:50: 	Executing 2 test(s) for 'addressbook.feature'
LOG             shared/scripts/Feature.js:11: 	Executing scenario '创建的初始状态'
LOG             shared/scripts/Feature.js:27: 	Executing step: Given 没有现有的地址簿
LOG		shared/scripts/Feature.js:27:	Executing step: When 我创建一个新的地址本
LOG		shared/scripts/Feature.js:27:	Executing step: Then 没有参赛作品应该存在
PASS		tst_addressbook/test.js:19: 	Comparison       '0' and '0' are equal
LOG           	shared/scripts/Feature.js:11:	Executing scenario '添加首次条目后的状态'
LOG             shared/scripts/Feature.js:27: 	Executing step: Given 一个新创建的地址
LOG            	shared/scripts/Feature.js:27:	Executing step: When 进入第一个人
LOG             shared/scripts/Feature.js:27:	Executing step: Then 应该存在一个条目
PASS           	tst_addressbook/test.js:36: 	Comparison       '1' and '1' are equal
END_TEST_CASE   End 'tst_addressbook'           End of test case 'tst_addressbook'

And here is the result summary:
*******************************************************
Summary:
Number of Test Cases:	1
Number of Tests:          	2
Number of Errors:          	0
Number of Fatals:          	0
Number of Fails:           	0
Number of Passes:          		2
Number of Expected Fails:          	0
Number of Unexpected Passes:      	0
Number of Warnings:        		0
*******************************************************

外表

框架可能的扩展: