Use the BDD(Cucumber) to test the RESTful API.
-
Install in your project:
npm install --save-dev api-bdd-test mocha chai supertest loopback-supertest -
mkdir
testin your project root folder -
generate the
mocha.optsfile in the test folder:--timeout 10000 --ui spec --growl --colors node_modules/api-bdd-test/index.js
- Or run
mocha --ui spec node_modules/api-bdd-test/index.jsdirectly.
-
generate the
.api-bdd-test.json|.cson|.ymlin the root folder or test folder:language: English server: "http://localhost:3000" root: "/api" libs: "./libs" steps: "./steps" features: "./features"
The feature specifications in the features folder for reading and testing.
The language is the default bdd language used in the specifications.
The server is the api server default url.
The libs, steps and features are the folders to store. the defauls is to
in the test folder.
- test
- ./features
- a.feature
- ./steps
- a.steps.js
- b-step.js
- ./libs
- some.lib.js
- some.dict.js
- ./features
- tag with
@onlybefore the scenario to execute the scenario only. - tag with
@pendingbefore the scenario to stop the scenario. - tag with
@beforebefore the scenario to turn the scenario to a before feature hook. - tag with
@afterbefore the scenario to turn the scenario to a after feature hook. - tag with
@beforeEachbefore the scenario to turn the scenario to a before each scenario hook. - tag with
@afterEachbefore the scenario to turn the scenario to a after each scenario hook. - tag with
@beforeStepbefore the scenario to turn the before each step hook. - tag with
@afterStepbefore the scenario to turn the after each step hook.
@only
Scenario Calc two valuelanguage supports with:
- File name postfix: a.english.feature
- first line of the file:
# language: English
the server, root/app, resource could be setting in .api-bdd-test.json|.cson|.yml file.
Or as the annotations in a feature file.
the genernal api steps:
/(GET|HEAD|DEL(?:ETE)?)\s+$string//(GET|HEAD|DEL(?:ETE)?|POST|PATCH|PUT)\s+$string[:]\n$object/- the object is cson format
- data: send to
- heads:
- type: accepting the canonicalized MIME type name complete with type/subtype, or simply the extension name such as "xml", "json", "png", etc, defaults to 'json'
- queries:
- fields:
- accepts:
- attachments:
- explain to see http://visionmedia.github.io/superagent/
/(?:last|prev(?:ious)?)\\s+results?\s+(?:should\s+)?(be|is|are|includes?)\n$object//(?:last|prev(?:ious)?)\s+status\s*(?:code)?\\s*(?:should\\s+)?((?:be|is)(?:n't|\s+not)?)\s*[:]?\s*$integer/- keep the
result.body.idto 'myvar'
eg,
Feature: Standard API Test
@before
Scenario: empty data before feature running
Given DELETE "bottle"
Scenario: POST and Get result
# POST 'http://127.0.0.1:3000/api/bottle'
# with data
#
Given POST "bottle":
----
type: 'json'
data:
id: 10
a: 13
----
Then The last status code should be: 200
And The last status code should be not: 400
And The last result should be:
----
id: 10
a: 13
----
And keep the result of "body.id" to "myid"
And keep the `result.body.id` to "myid1"
And keep the result to "myres"
And expect the stored `myid` equal 10
And expect the stored `myid1` equal 10
And expect the stored `myid` is not equal 0
And expect the kept `myid` least 1the genernal Chinese api steps:
新建资源:"resource",其内容为\n$object编辑(ID|编号)是:"the-id"的资源:"resource",其内容为\n$object删除(ID|编号)是:"the-id"的资源:"resource"检[查测]是否存在资源\\s*[::]?[(( ]$identifier(?:[)) ]\\s*[,,.。])?\\s*[::]?$string/上次[的]?(?:状态[码]?|status)[为是::]\s*$identifier//上次[的]?(?:结果|body)([为是::]|包[括含][::]?)\s*\n$object/(?:获[取得]|取[得]?)(?:id|ID|编号)[为是::]?$string的?资源\\s*[::]?[((]?$identifier(?:[))]?\\s*[,,.。])?[的其]?(?:内容|结果)[为是]?\\n$object(?:获[取得]|取得?)资源\\s*[::]?[((]?$identifier(?:[))]?\\s*[,,.。])?\\s*[::]?$string([不]?会?存在|没有?|有)(?:id|ID|编号)[为是::]?$string的?资源\\s*[::]?[((]?$identifier(?:[))]?\\s*[,,.。])?/登[录陆]\s*用户[::]\s*$string\s*[,,]\s*密码[::]\s*$string//注销用户|退出系统//(?:记[住下忆]?|保[存留])结果的(?:属性)?$string到[::]?$string/记住结果到"myvar"保存的"mvar"等于xxx/(不?存在)(?:记[住下忆]?|保[存留]的)?\s*$string$/列[出举]资源\\s*[::]?[(( ]$identifier(?:[)) ]\\s*[,,.。])?[搜查][索询找]资源\\s*'+resNameRegEx+'按?(?:指定|如下)?(?:条件|设置)[::]?$object记住`result.body[0].id`到"myvar"获得id为"id",过滤条件为"xxx"的资源: bottle
The all scripts in the libs folder will be loaded.
The a.steps.js script in the steps folder will be loaded for a.feature.
The steps script file extend name should be end with [.-]step[s]?\\.(js|coffee)
The libs script(extend name should be end with[.-](lib[s]?|dict[s]?)\.(js|coffee)) should be like this:
var Dictionary = Yadda.Dictionary;
var converters = Yadda.converters;
module.exports = function(dictionary){
dictionary
.define('integer', /(\d+)/, converters.integer);
this
.define('Expect $integer to be an integer', function(i, next) {
assert.equal(typeof i, 'number');
assert(i % 1 === 0);
next();
});
}The steps script(file name should be #{featureName}(.#{lang})?.step[s]?.(js|coffee)) should be like this:
//the `this` is the Yadda.Library() (bind to current language)
//the dict is the Yadda.Dictionary()
module.exports = function(dict){
this.given("$integer green bottles are standing on the wall", function(number_of_bottles) {
wall = new Wall(number_of_bottles);
wall.printStatus();
})
.when("$integer green bottle accidentally falls", function(number_of_falling_bottles) {
wall.fall(number_of_falling_bottles);
console.log("%s bottle falls", number_of_falling_bottles);
})
.then("there are $integer green bottles standing on the wall", function(number_of_bottles) {
assert.equal(number_of_bottles, wall.bottles);
wall.printStatus();
});
}- no back ref in regexp.
- no optional group on
$xxxdefininition. eg,$string?should be wrong. - report the
<-- Undefined Steperror:- Duplication Regexp Step
- Optional Group in the regexp step.
- [Broken] the
resNameRegEx(Chinese) force use limiter to get the identifier.
- Add Special Scenarios
- add the before/after annotations for feature hook
- add the beforeEach/afterEach annotations for Scenario hook
- add the beforeStep/afterStep annotations for step hook
- referernce the variaible which stored by steps. use the "``" delimiter instead.
- it's an one line coffee-script code in this delimiter.
\"#{myid}"``
- it's an one line coffee-script code in this delimiter.