TDD JavaScript With Require.js and Teabag on Rails

Introduction

Test Driven Development, or TDD, is the process of writing tests before writing your code. Or minimally, testing the code that you write.

Since starting to use require.js, I found it annoying that there were not many test runners in rails that would support require. I did find that Teabag had partial require support by defering the execution of tests until certain assets are loaded.

However, once we integrated Teabag, we found that it didn’t always wait correctly. We also needed to hardcode or use our templating language output JavaScript that would include all our tests, even though Teabag knew what all our tests were. So like anyother developer, we modified Teabag, added a use_require option to a test suite, then sent them a pull request on GitHub.

Our modifications basically used require itself, to include the found tests (see: suite.matcher) and pull them in, then once loaded, run Teabag.execute. This guarantees that all the dependencies and such are loaded, because it uses require itself.

Setting up Teabag

First we need to add the gem to your Gemfile.

Gemfile

# you may have to add :github => 'modeset/teabag' to get the latest
gem 'teabag'

Now run their rake installer. In this case I will use mocha.

$ rails generate teabag:install --framework=mocha

Then setup your test suite.

config/initializers/teabag.rb

# This isn't the only thing in your teabag.rb
# just how to activate using require in the suite portion
config.suite do |suite|
# Activate require
suite.use_require = true

# File Matcher
suite.matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.coffee,coffee}"
# there is a lot more including your spec helper
end

Now we will include chai into our spec helper. You can use any assertion library you want. I just like chai. We are also bringing in application.js though all it is doing for me is including any vendors assets, so you might not need to do this.

spec/javascripts/spec_helper.js

//= require support/chai
//= require application

Writing a test

Now let’s write a simple test. First we will add a model to app/assets/javascripts/Model.js

app/assets/javascripts/Model.js

define([] , function () {
var Model = function (firstName , lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Model.prototype.getFullName = function () {
return this.firstName + ' ' + this.lastName;
};
return Model;
});

Now you can see the model takes two params, a first name and a last name, then has a single function called getFullName, which concats the two.

Now we will write our spec in spec/javascripts/Model_spec.js. The reason we use _spec.js suffix, is so that Teabag can find it, via the suite’s matcher setting.

spec/javascripts/Model_spec.js

define(['Model'] , function (Model) {
describe('Model' , function () {
it('#getFullName should provide the full name' , function () {
var m = new Model('Inline' , 'Block');
chai.expect(m.getFullName()).to.equal('Inline Block');
});
});
});

Now we will startup our rails server and hit up the the /teabag in our browser and it should run and execute our test.