node package manager

barriertest

Barrier

Build Status

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(23)).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