Working with Javascript can be, at best, a mildly frustrating experience. As I've started to work more with Jasmine and Backbone.js, I've added some simple points to my Javascript checklist that make the experience more palatable.
When I began using these tools, I found myself spending inordinate amounts of time figuring why my tests were failing instead of keeping to a short red-green-refactor cycle time. The following is a contrived example, but it does illustrate how easy it is to create errors that are hard to track down as you begin to use Jasmine.
Let's say you're working on a simple Todo Rails app using Backbone.js. You'll need a collection for your Todos, so you write a spec to require a certain model. Here's the first spec:
OK, we've got some failures - "TypeError: Cannot read property 'Todos' of undefined". We don't have a model yet, so we go create one:
All we really need to do is extend Backbone.Model without new options - we just want to define Todo.models.Todo for the sake of our test. We add this code and run the specs again:
Hmm, so we get the same failures even though we just defined the Todo.models.Todo. It turns out that for this case, jasmine.yml is the source of our frustration:
We're including all of our public/javascripts files, but we're still missing our model definition. The problem is that when you generate jasmine.yml with the Jasmine gem, it doesn't know about any of the dependencies your Javascript code has. In our first spec, we need to load the model before we load the collection. If you change your jasmine.yml to look like this:
You will enforce the loading of your models, then your collections, and then everything else. After this change, we finally get a proper failure in Jasmine:
And then we can write the following code to make the test pass:
On to test #2 - ensuring that the url for the collection is "todos":
Wait, 0 specs? Jasmine doesn't help you out much here, which is why I pretty much always have the Javascript console open in Chrome (or Firebug in Firefox).
We see there's an unexpected identifier on line 11, and I notice that I omitted the '.' in the second test. I add that in and my test fails for the right reason.
I add the url definition to my collection, and run my specs again.
Ah geez, failures all over. Jasmine is a little more helpful by explicitly showing the failing tests, but it's the console again that points you to the problem. In this case, I'm missing a comma at the end of the 'model: Todo.models.Todo' line in my collection. I add it in and my tests turn green.
After all that, I finally have a scant two specs passing for my Todos collection. The time it takes to troubleshoot these errors can be frustrating, and it's really only the beginning of issues you can have just using Javascript in general, let alone trying to test drive your Javascript code. If you:
- Run Jasmine with the browser's Javascript console open
- List your source files in the correct order inside jasmine.yml
Then you can start spending less time debugging and more time test driving.