Testing Backbone.js Best Practices
Talk to any startup these days about which client-side MVC framework they are using and you will hear about some awesome new framework. Now, if you ask them how they test the code they write using these frameworks, I bet most will give you a non-answer which equates to “we don’t test”. This is not so much their fault as it’s the infancy of these frameworks and the lack of good documentation on best practices.
Here at Involver, we selected Backbone.js as our client side framework because it has the largest community behind it and the most documentation. Even with the benefits of selecting Backbone, there was still little resources on best practices on testing Backbone.js code. I will now share with you some of the best insights we discovered while learning how to test Backbone.
Here are a few helper plugins that round out Jasmine:
- Jasmine-AJAX – Capture AJAX calls and stub return data.
- Jasmine-jQuery – Adds helper expectations, e.g. toHaveText(), toHaveClass()
- Sinon.js – Awesome stubbing framework. We use it to mock the clock for setTimeout/setInterval.
- facebook-js-stub – Facebook JS API stubbing framework we built in house. Handles user auth/login state as well as API calls to Facebook.
Don’t Use the DOM, Use Objects
One of the best features of Backbone, is the lack of reliance on the DOM. By default a Backbone view will create an in-memory jQuery object containing a single DIV element. By convention, you should use this element as the target of your view’s content and then pass in your target as the el param on the views instantiation. The beauty of this is that we do not need a DOM to instantiate and render a Backbone view, everything is done in memory!
This means we don’t have to see the ugly injecting and removing of content on the page as the tests run, there is no need to clean up the DOM after each test iteration, and our test suite will run much faster.
Always Scope DOM Queries
This is not so much a Backbone thing as a basic jQuery principle, but it becomes very important when testing in-memory objects. A normal jQuery global DOM query looks something like
This works when you have access to a DOM, but what happens when you test an object that does not exist on the DOM? This is where scoped queries are essential. Backbone views supply a scoped element just for this.
This allows your code to be more modular, since you will not have to worry about element pollution as much, and you can test it!
Don’t Worry About the Little Things
Jasmine tests should be insanely quick. A good benchmark is 1 second per 100 tests. The moment you start doing integration style testing in Jasmine, you will be drastically slowing down your test suite. Here is an example of a simple view test.
Testing, Do It!