Skip to content

Commit

Permalink
Adds an optional BDD testing idiom.
Browse files Browse the repository at this point in the history
The 'whiskey' package now exports a 'bdd' symbol which can be required to enable BDD-style tests:

var bdd = require('whiskey').bdd.init(exports);

This wraps the exports object of the test module and translates the BDD tests into whiskey tests
so they run normally.

The one adaptation of the BDD idiom for whiskey is that test suite and spec functions being passed
to describe() and it() need to accept a function parameter, respectively it() and expect() - this
is to support the whiskey behavior of injecting (test, assert) into each test individually.
  • Loading branch information
robert-chiniquy committed May 29, 2012
1 parent 66bb309 commit 69c474a
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
@@ -1,6 +1,9 @@
Changes
=======

* Add an optional, minimal BDD idiom implementation.
[Robert Chiniquy]

* Send the SIGKILL signal instead of SIGTERM when killing child processes managed by the process runner.
[Robert Chiniquy]

Expand Down
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -123,6 +123,18 @@ exports['test_two_equals_one'] = function(test, assert) {
}
```

A simple example using the optional BDD module:
``` javascript
var bdd = require('whiskey').bdd.init(exports);
var describe = bdd.describe;

describe('the bdd module', function(it) {
it('supports it(), expect(), and toEqual()', function(expect) {
expect(true).toEqual(true);
});
});
```

For more examples please check the `example/` folder.

# Build status
Expand Down
39 changes: 39 additions & 0 deletions example/test-bdd-failures.js
@@ -0,0 +1,39 @@
/*
* Licensed to Cloudkick, Inc ('Cloudkick') under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Cloudkick licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var bdd = require('../lib/bdd').init(exports);
var describe = bdd.describe;

describe('the bdd expect()', function(it) {

it('correctly fails toBeNull()', function(expect) {
expect("not null").toBeNull();
});

it('correctly fails toBeDefined()', function(expect) {
expect(undefined).toBeDefined();
});

it('correctly fails toBeUndefined()', function(expect) {
expect(true).toBeUndefined();
});

it('correctly fails toMatch()', function(expect) {
expect('fish').toMatch(/not a fish/);
});

});
69 changes: 69 additions & 0 deletions example/test-bdd.js
@@ -0,0 +1,69 @@
/*
* Licensed to Cloudkick, Inc ('Cloudkick') under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Cloudkick licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var bdd = require('../lib/bdd').init(exports);
var describe = bdd.describe;
var beforeEach = bdd.beforeEach;

var wasBeforeEachCalled = false;

beforeEach(function() {
wasBeforeEachCalled = true;
});

describe('the bdd module', function(it) {

it('supports it(), expect(), and toEqual()', function(expect) {
expect(true).toEqual(true);
});

it('supports beforeEach()', function(expect) {
expect(wasBeforeEachCalled).toEqual(true);
});

it('supports async tests', function(expect, callback) {
var called = false;
setTimeout(function() {
called = true;
}, 1);
setTimeout(function() {
expect(called).toEqual(true);
callback();
}, 3);
});

});

describe('the bdd expect()', function(it) {

it('handles toBeNull()', function(expect) {
expect(null).toBeNull();
});

it('handles toBeDefined()', function(expect) {
expect(true).toBeDefined();
});

it('handles toBeUndefined()', function(expect) {
expect(undefined).toBeUndefined();
});

it('handles toMatch()', function(expect) {
expect('fish').toMatch(/is/);
});

});
1 change: 1 addition & 0 deletions index.js
Expand Up @@ -15,5 +15,6 @@
* limitations under the License.
*/

exports.bdd = require('./lib/bdd.js');
exports.run = require('./lib/run.js').run;
exports.installCoverageHandler = require('./lib/coverage').installCoverageHandler;
97 changes: 97 additions & 0 deletions lib/bdd.js
@@ -0,0 +1,97 @@
/*
* Licensed to Cloudkick, Inc ('Cloudkick') under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Cloudkick licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var sprintf = require('sprintf').sprintf;

function Expect(actual) {
this._actual = actual;
}

/**
* @param {Object} imports The foreign exports object to add bdd tests to
* @returns {Object} bdd A collection of test functions
*/
exports.init = function(imports) {
var bdd = {
'_suiteSetup': function() {}
};

/** @param {Function} setup function to call before each suite */
bdd.beforeEach = function(setup) {
bdd._suiteSetup = setup;
};

/** @description creates a test suite
* @param {string} title
* @param {Function} suite
*/
bdd.describe = function(title, suite) {

/** @description it() is the equivalent of a exports['test blah'] in the whiskey idiom.
* This function, when called, adds a whiskey test to the imports object.
* @param {string} name
* @param {Function} spec(expect, callback)
*/
function it(name, spec) {
var whiskeyName = sprintf("test %s %s", title, name);

function expect(actual) {
return new Expect(actual);
}

/** @description Re-binds the Expect test methods using the newly-injected assert.
* @param {object} test the test object injected by whiskey
* @param {object} assert the assert object injected by whiskey
*/
imports[whiskeyName] = function(test, assert) {

// make the whiskey test and assert objects available to bdd tests
bdd.test = test;
bdd.assert = assert;

/** @description maps an assert method to a bdd matcher
* @param {string} assertion the name of a whiskey assert method
* @param {string} bddName the name of the equivalent expect method
*/
function translateMatcher(assertion, bddName) {
Expect.prototype[bddName] = function() {
assert[assertion].bind(this, this._actual).apply(this, arguments);
}
}

// This must be done each time a test is created,
// as test and assert are injected in each test function.
translateMatcher('equal', 'toEqual');
translateMatcher('isNull', 'toBeNull');
translateMatcher('isDefined', 'toBeDefined');
translateMatcher('isUndefined', 'toBeUndefined');
translateMatcher('match', 'toMatch');

spec(expect, test.finish);
if (spec.length === 1) {
// if spec isn't expecting test.finish as an async callback, call it directly
test.finish();
}
}
}

bdd._suiteSetup();
suite(it);
};

return bdd;
}
17 changes: 17 additions & 0 deletions test/run.sh
Expand Up @@ -268,6 +268,23 @@ if [ $? -ne 0 ]; then
exit 1
fi

"${CWD}/bin/whiskey" --timeout 1000 \
--tests "${CWD}/example/test-bdd.js"

if [ $? -ne 0 ]; then
echo "BDD test didn't exit with zero exit code."
exit 1
fi

"${CWD}/bin/whiskey" --timeout 1000 \
--tests "${CWD}/example/test-bdd-failures.js"

if [ $? -ne 4 ]; then
echo "BDD failure test didn't fail as expected."
exit 1
fi


echo ""
echo "* * * Whiskey test suite PASSED. * * *"
exit 0

0 comments on commit 69c474a

Please sign in to comment.