抽时间看了下cucumber的js版本,分享下自己写的示例。代码地址: https://github.com/lccf/codelibrary/tree/master/tscucumber

更新

  • 2017/01/25 更新cucumber版本和ts提示库,使用defineSupportCode语法。

环境配置

1.创建目录

1
2
3
4
5
mkdir ts-cucumber
cd ts-cucumber
mkdir -p features/step_definitions features/support src/step_definitions src/support
echo '{}' > package.json
npm install typescript cucumber webdriverio cucumber-assert @types/cucumber @types/webdriverio --save-dev

2.安装selenium-standalone

1
2
3
npm install selenium-standalone -g
# baseUrl参数设置淘宝mirror
selenium-standalone install --baseURL=http://npm.taobao.org/mirrors/selenium

3.创建ts配置文件,设定ts编译选项,源代码目录为src,目标代码目录为features
tsconfig.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"sourceMap": true,
"removeComments": false,
"lib": [
"es6",
"dom",
"scripthost",
"es2015.generator",
"es2015.promise"
],
"sourceRoot": "src",
"outDir": "features"
}
}

4.添加npm启动脚本,编译ts后启动cucumberjs
package.json

1
2
3
"scripts": {
"start": "tsc -p . && cucumberjs"
},

编码

1.添加测试需求描述文件
features/bing_search.feature

1
2
3
4
5
6
Feature: 必应搜索
Scenario: 搜索cucumber
Given 我访问 "https://www.bing.com"
When 我输入 "cucumber"
And 我点击 "搜索"
Then 页面标题中应包含 "cucumber"

2.添加cucumber-assert定义文件
src/declare/cucumber-assert.d.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
declare namespace CucumberAssert {
export let equal: (actual: any, expected: any, callback: () => any, message?: string) => void;
export let notEqual: (actual: any, expected: any, callback: () => any, message?: string) => void;
export let deepEqual: (actual: any, expected: any, callback: () => any, message?: string) => void;
export let notDeepEqual: (actual: any, expected: any, callback: () => any, message?: string) => void;
export let strictEqual: (actual: any, expected: any, callback: () => any, message?: string) => void;
export let notStrictEqual: (actual: any, expected: any, callback: () => any, message?: string) => void;
export let throws: (block: any, callback: () => any, error?: any, message?: string) => void;
export let doesNotThrow: (block: any, callback: () => any, message?: string) => void;
export let ifError: (value: any, callback: () => any, message?: string) => void;
}

declare module "cucumber-assert" {
export = CucumberAssert;
}

3.添加world支持文件
src/support/world.ts

1
2
3
4
5
6
7
8
9
import { defineSupportCode } from 'cucumber';

function CustomWorld() {

}

defineSupportCode(function({ setWorldConstructor }: any) {
setWorldConstructor(CustomWorld);
});

4.添加hook文件,初始化浏览器client
src/support/hook.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import * as webdriverio from 'webdriverio';
import { defineSupportCode, CallbackStepDefinition, Hooks, HookScenario } from 'cucumber';

let client: WebdriverIO.Client<void> = null;

let initClient = function(callback: CallbackStepDefinition) {
let options: WebdriverIO.RemoteOptions = {
desiredCapabilities: {
browserName: 'chrome'
},
logLevel: 'silent',
baseUrl: 'http://localhost:3000'
};

client = webdriverio
.remote(options)
.init()
.setViewportSize({ width: 800, height: 768 }, true)
.getViewportSize().then(size => console.log(size))
.call(callback);
}

defineSupportCode(function({ Before, After, registerHandler}: Hooks) {
registerHandler('BeforeFeatures', function(features: any[], callback: CallbackStepDefinition) {
initClient(callback);
});

Before(function(scenarioResult: HookScenario, callback: CallbackStepDefinition) {
this.client = client;
callback();
});
registerHandler('AfterFeatures', function(features: any[], callback: CallbackStepDefinition) {
client.end().call(callback);
});
});

5.添加测试定义代码
src/step_definitions/bing_search_steps.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { defineSupportCode, CallbackStepDefinition, StepDefinitions } from 'cucumber';
import * as assert from 'cucumber-assert';

defineSupportCode(function({ Given, Then, When }: StepDefinitions) {
let client: WebdriverIO.Client<void>;

Given('我访问 {arg1:stringInDoubleQuotes}', function (pageUrl: string, callback: CallbackStepDefinition) {
client = this.client;
client.url(pageUrl).call(callback);
});

Then('我输入 {arg1:stringInDoubleQuotes}', function (queryString: string, callback: CallbackStepDefinition) {
client = this.client;
client.setValue('#sb_form_q', queryString).call(callback);
});

Then('我点击搜索', function(callback: CallbackStepDefinition) {
client = this.client;
client.click('#sb_form_go').call(callback);
});

When('页面标题中应包含 {arg1:stringInDoubleQuotes}', function (title: string, callback: CallbackStepDefinition) {
client = this.client;
client.waitForVisible('#b_results', 3000).then(() => {
client.getTitle().then(pageTitle => {
assert.notEqual(pageTitle.match(title), null, callback, `页面标题中不包含${title}`);
});
});
});
});

执行

1
2
3
4
# 先启动selenium服务
selenium-standalone start
# 执行cucumberjs
npm start

链接

cucumber https://github.com/cucumber/cucumber-js
webdriverio http://webdriver.io/
cucumber-assert https://github.com/djungowski/cucumber-assert

*示例代码基于cucumber 2.0.0-rc.6版本,与最终cucumber 2.0最终版可能存在不兼容。