Testing CoffeeScript for Rails with Jasmine
Before, I lamented about the testing story for Coffeescript in Rails. This is a description of a process that I am currently using. It is not perfect (and I'll end on why I do not think so) but it checks about 75% of the boxes on my Want list.
First, I just want to give a quick start guide for anyone that wants to just get shit done. I will dive into some details after this section--so if you're interested in how it works or are debugging something, that part will be of more interest.
First, we're going to create a Rails application.
rails new testing_coffeescript
It will generate output like so
create create README.rdoc create Rakefile ... Using sqlite3 (1.3.5) Using uglifier (1.2.3)
Next, you'll need a couple more gems. Edit your Gemfile to include
group :development do gem 'jasmine' gem 'jasminerice' end
The jasmine gem will come with some generators. I actually prefer to NOT use them and 'roll my own' scaffold because its easier to get to work with jasminerice.
//= require application //= require_tree .
/* *= require application */
And now you should be ready to run specs. Start your rails server (
rails s) and hit http://localhost:3000/jasmine.
describe "sanity", -> it "1 should == 1", -> expect(1).toBe(1)
Save the file, run the tests by refreshing the browser and now you should see "1 spec, 0 failures". Finally, there is one last step to testing your coffeescript. Lets assume we had this class:
class Seven add: (anotherNumber) -> 7 + anotherNumber
and a test
it "should add 7 to be 14", -> expect(new Seven().add(7)).toBe(14)
you may scratch your head at why you will get an error saying
ReferenceError: Seven is not defined. Essentially, this is because Seven is not in scope. You have to add a line to your code to make it available for testing:
class Seven add: (anotherNumber) -> 7 + anotherNumber window.Seven = Seven
And now you're all set to write tests for your coffeescript!
How it Works
Most of the work is being done by the Rails asset pipeline and the jasminerice middleware. The Rails asset pipeline can give us compiled coffeescript on-demand and we do not have to compile it manually. It also does all the includes heavy lifting for us (yay! No having to manage test lists).
The jasminerice middleware uses the Rack API that Rails sits on top of in order to intercept any requests that go to /jasmine and request all the necessary bits and pieces. We actually aren't hitting Rails at all when we hit /jasmine.
We run these tests in our CI environment using jasminerice, as well. We use phantomjs to run them headlessly. Phantomjs does need a runner file which we've lifted from the guard-jasmine gem (On GitHub). We spin up a rails server (we picked port 5555) and then run the tests against it.
- Running tests by refreshing a browser is cludgy and does not integrate well in the development process.
- We run tests differently in development than we do for CI. In theory they are the same but we have already run into issues where that was not the case.
- The output for the phantomjs runner we are using is ugly. This can be readily fixed but just needs some time and elbow grease.
- Running tests with a DOM hides issues with code that is tightly coupled to the DOM.
And that's pretty much it. It's quite a nice setup otherwise!