getting started for tdd using jasmine and backbone.js

Developing in javascript is a fun and exciting process.  Debugging code in the browser using firebug can provide instant gratification.  Good test coverage is a must when the code you write could potentially be executed in any number of platforms. Writing unit tests isn't always a priority and peace of mind can be hard to come by, but one way of dealing with the uncertainty is to practice test driven development.  Using this style means that you write the test before the code and theoretically everything you write already has test coverage. This makes it less stressful to maintain and refactor your codebase. Behavior Driven Design is an extension of this philosophy that provides a higher level understanding of what can be expected from the code you write. You still have to write unit tests, but they are attached to specifications of the behavior.  There are many frameworks for TDD and BDD and I am going to explore jasmine, which is a more recent addition to the javascript testing world. I am also interested in checking out backbone.js, which is a MVC style framework for writing javascript applications.  Most developers are familiar with frameworks like django and rails for writing traditional web apps in python and ruby.  For those of us who are interested in providing more a more dynamic experience, javascript is the language of choice.  It also makes sense to farm out the workload to user's computers rather than wasting valuable server side processing power. Setting up jasmine to work with backbone.js is fairly straightforward.  I did run into a few snags and I thought it might be useful to document the process I went through.  I'm assuming you are using a mac or linux computer and are familiar with the command line. First download the jasmine testing framework.  We need the jasmine standalone distribution. mkdir project; cd project curl -O http://pivotal.github.com/jasmine/downloads/jasmine-standalone-1.0.2.zip unzip jasmine-standalone-1.0.2.zip rm jasmine-standalone-1.0.2.zip This creates the basic jasmine framework in your project directory. You can run the sample tests by opening the SpecRunner.html file in any browser.  This file is where you specify the javascript libraries that you would like to load as well as your own test and production code. The light is green and all tests pass.  Congratulations! Inside the project directory that we created there are subdirectories called src and spec.  Src is where production js files go and spec is where we will store our test code.  Right now there are sample files in place which you can use as an example for the new project. Let's create two files, "src/app.js" and "spec/spec_app.js". These sample files are loaded by modifying SpecRunner.html to look like this: If we reload SpecRunner.html, there will be no failures because we have not actually added any tests at this point. The first step in TDD is to write a test that should fail and then write just enough code to make it pass. For this example I am going to start creating a backbone.js model. There are a few introductory backbone.js tutorials, including this one by the antipodean Thomas Davis. For simplicity's sake, I'll be following this more barebones guide. Let's create our first test in src/spec_app.js: describe("backbone", function() { it("model should have name", function() { model = new Model({ name: 'Model A'} ); expect(model.get('name')).toEqual('Model A'); }); }); Reloading SpecRunner.html will give you the following result. [caption id="attachment_358" align="aligncenter" width="721" caption="Model is not defined"][/caption] The fact that Model is not defined shouldn't bother us because we haven't written code to define it, yet. That would be the next step. In src/app.js, add the following line to start stubbing out our first model: var Model = Backbone.Model.extend(); Unfortunately we still don't have a passing test. We have not yet incorporated backbone.js into our project, so the code we are calling does not exist, yet. To fix this problem we download a copy of backbone.js into our src directory with the following commands. wget http://documentcloud.github.com/backbone/backbone.js mv backbone.js src Now we will edit SpecRunner.html and add a reference to this new file. Since we are confident that our test is being executed we can remove the example files and references from SpecRunner.html. It should look like this: Now we can reload SpecRunner.html and see if our test passes. Unfortunately we still don't have a green light. We can get more information by opening the javascript console. This is a great way to troubleshooting fail tests because you can see console logs and debug the code interactively. Here is what showed up in the console after executing the test. The error is: "Uncaught TypeError: Cannot call method 'extend' of undefined". Unfortunately backbone's model code seems to be missing the extend method, which is unfortunate as our code relies on it. Fortunately other people have this problem and it has been hashed out on stackoverflow. Bonebone.js has a dependency on underscore.js, an awesome little utility library. So let's grab a copy of that and add it to our project like we did with the backbone.js file. wget http://documentcloud.github.com/underscore/underscore.js mv underscore.js src We also need to add a reference to the library in SpecRunner.html, which should have lines that look like this: Now when we reload SpecRunner.html to run our tests we finally see some green. We have our first test passing and a framework for building a robust dynamic javascript application using a modern MVC framework. The test first method requires some discipline but ideally ought to keep you from getting angry calls in the middle of the night. This example project can be cloned from github for your enjoyment. git clone git@github.com:eknuth/jasmine_backbone.git