barriertest v0.4.1
Barrier
A test framework that embraces promises for real
Installation
npm install barriertest
Basic Testing
This part describes the regular sync tests.
Barrier uses RSpec-like syntax to describe tests, and it bundles Chai as the assertion framework, as so:
// Javascript
describe("MyObject", function() {
it("sums two numbers", function() {
expect(sum(2, 3)).to.eq(5);
});
});
# Coffeescript
describe "MyObject", ->
it "sums two numbers", ->
expect(sum(2, 3)).to.eq(5)
You can nest describe blocks as you like:
// Javascript
describe("MyObject", function() {
describe("some internal", function() {
it("do something", function() {
expect(something()).to.eq(true);
});
});
});
# Coffeescript
describe "MyObject", ->
describe "some internal", ->
it "do something", ->
expect(something()).to.eq(true)
We support before
, beforeEach
, after
and afterEach
clauses:
// Javascript
describe("MyObject", function() {
var someVar = null;
before(function() { someVar = "hello"; });
it("must set someVar", function() {
expect(someVar).to.eq("hello");
});
});
# Coffeescript
describe "MyObject", ->
someVar = null
before -> someVar = "hello"
it "must set someVar", ->
expect(someVar).to.eq("hello")
Also, we support lazy blocks for dependency injection:
// Javascript
describe("MyObject", function() {
lazy("value", function() { return 50; });
it("loads the value", function(value) {
expect(value).to.eq(50);
});
});
# Coffeescript
describe "MyObject", ->
lazy "value", -> 50
it "loads the value", (value) ->
expect(value).to.eq(50)
Note that the we do a reflection on the function to extract the variable name, them we lookup and build it for each test.
And you can inject dependencies on each other:
// Javascript
describe("MyObject", function() {
lazy("value", function() { return 50; });
lazy("value2", function(value) { return value + 10; });
it("loads the values", function(value2) {
expect(value2).to.eq(60);
});
});
# Coffeescript
describe "MyObject", ->
lazy "value", -> 50
lazy "value2", (value) -> value + 10
it "loads the values", (value2) ->
expect(value2).to.eq(60)
Async Testing
For basic async testing, you can call async
into the current object to make the test wait:
// Javascript
describe("Awesome", function() {
return it("supports async testing", function() {
var done = this.async();
setTimeout(function() {
expect(true).to.be["true"]();
done();
}, 50);
});
});
# Coffeescript
describe "Awesome", ->
it "supports async testing", ->
done = @async()
setTimeout ->
expect(true).to.be.true()
done()
, 50
Despites the support on simple async testing, we really recommend you to use promises instead, as described on the next section.
Promises Testing
We recognize that there is a lot of async code into Node, and also, we recognize that promises have a great value in helping to write better async code.
That's why Barrier supports and recommends promises usage over the entire testing process.
But actually there is not much to say about the usage, because it's just transparent! You can just use promises as values and we handle the rest!
Check some examples:
// Javascript
describe("Using Promises", function() {
it("can use promises as values on expectations", function() {
expect(loadUser(30)).to.haveProperty("age", fetchRemoteAge());
});
});
# Coffeescript
describe "Using Promises", ->
it "can use promises as values on expectations", ->
# imagine that loadUser and fetchRemoteAge are functions that returns
# promises that will eventually handle de values
expect(loadUser(30)).to.haveProperty("age", fetchRemoteAge())
Also, if your test returns a promise, the runner will wait for it:
// Javascript
describe("Delaying the runner", function() {
it("will wait for my promise", function() {
return Q("value").delay(30).then(function(v) {
expect(v).to.eq("value");
});
});
});
# Coffeescript
describe "Delaying the runner", ->
it "will wait for my promise", ->
Q("value").delay(30).then (v) ->
expect(v).to.eq("value") # and that's it, Barrier will do the async handling magic
Before and after blocks does the same, if you return promises on they, the runner will wait before going on:
// Javascript
describe("Before promise me...", function() {
var user, userDecorated;
before(function() {
// it's important that you return the promise here so Barrier will know
// that it needs to wait for it. In Coffeescript it's more transparent
// since Coffeescript always return the last statement
return loadUser().then(function(u) {
user = u;
});
});
// note that before blocks run in series, so, it's safe to expect that previous
// before blocks are done
before(function() { userDecorated = decorateUser(user); });
it("is awesome", function() {
expect(userDecorated).to.not.be["null"];
});
});
# Coffeescript
describe "Before promise me...", ->
user = null
userDecorated = null
before -> loadUser().then (u) -> user = u
# note that before blocks run in series, so, it's safe to expect that previous
# before blocks are done
before -> userDecorated = decorateUser(user)
it "is awesome", -> expect(userDecorated).to.not.be.null
But remember about Lazy Attributes? They can be promises too!
// Javascript
describe("Lazy Promises", function() {
lazy("user", function() { return findUserOnDB(); });
it("will load the promise and inject it!", function(user) {
expect(user.name).to.eq("sir");
});
});
# Coffeescript
describe "Lazy Promises", ->
lazy "user", -> findUserOnDB()
it "will load the promise and inject it!", (user) ->
expect(user.name).to.eq("sir")
And even better, you can do it while injecting lazy dependencies!
// Javascript
describe("Lazy Promises Dependencies!", function() {
lazy("store", function() { return createStoreOnDb(); });
lazy("user", function(store) {
return createUser({store: store.id});
});
it("will load gracefully", function(user) {
expect(user.store).not.null;
});
});
# Coffeescript
describe "Lazy Promises Dependencies!", ->
lazy "store", -> createStoreOnDb()
lazy "user", (store) -> createUser(store: store.id)
it "will load gracefully", (user) ->
expect(user.store).not.null
Get much more examples here
TODO (PR's would be welcome):
- Separate Interface code from Suite
- Verbose mode logging each step block
- Isolated tests flag (for parallel testing)
- TDD Interface