Apps, suites, and examples for Backbone.js test development.
This site provides materials and resources for developing and testing Backbone.js web applications. All of the application and test examples for the book Backbone.js Testing can be found here, grouped by chapter. We also provide a reference Backbone.js application - Notes - for creating and viewing notes, which we use throughout the examples in the book.
The core set of Backbone.js application technologies we cover includes:
We write a test infrastructure built on the following (fantastic) test libraries.
The source code for everything is available from the project's GitHub repository. If you find any errors or issues in content or code, please file a bug report and we'll fix things up in short order. For those interested in extending our testing examples or helping out, please see our contribution and development guide.
Backbone.js Testing by Ryan Roemer walks through the fundamentals of test-driven development for Backbone.js applications. All of the code samples are directly used in the book - it is essentially your narrative guide to this repository.
A short description of the book from the Packt Publishing website:
Frontend web applications are soaring in popularity and the Backbone.js library is leading this charge with a modular, lightweight approach for organizing JavaScript web applications. At the same time, testing client-side JavaScript and Backbone.js programs remains a difficult and tedious undertaking.
Backbone.js Testing brings sensible practices and current techniques to the challenges of Backbone.js test development. The book introduces fundamental testing concepts, comprehensive test infrastructure design, and practical exercises to easily and systematically test modern JavaScript web applications.
The book progresses from Mocha test suites and Chai assertions to advanced test mocks and stubs with Sinon.JS. The requisite libraries and utilities are introduced with in-depth examples and best practices for integration with your applications. The book guides you through the test planning and implementation processes for your application models, views, routers, and other Backbone.js components.
Backbone.js Testing gives you the tools, examples, and assistance to test your Backbone.js web applications thoroughly, quickly, and with confidence.
Ryan and the team at Formidable Labs assist developers, from startups to Fortune 500 companies, with all aspects of Backbone.js web application and test development. At Formidable, we lead high-impact training sessions, build out some of the world's largest Backbone.js applications, and help get new projects of any size off the ground.
Once you finish Backbone.js Testing, please reach out to us -- we'd love to accelerate your Backbone.js development and education.
The application and test samples should work for the following browser / version combinations:
See the Chai installation notes for
more compatibility information. Note that the Chai should
object
prototype extension is not compatible with IE 9 and lower.
Notes is a simple personal note manager, written in
Backbone.js. We provide two versions - a "quick and easy" localStorage
based
application that works in your browser with no additional setup, and a
"classic" application with a full REST backend.
The Notes application home page lists existing notes (by creation date), and provides a form field to create a new note with a title. A filter field is available in the menu bar to limit the list of displayed notes by title.
Clicking on the edit icon brings us to the single note view, with a simple form editor for the title and text body fields of the note. The body of a note is written using Markdown formatting.
Clicking on the view menu tab switches us to the viewing pane, which renders the note's Markdown and produces our displayed note.
The Notes application is written using Bootstrap's responsive libraries and should render fine on mobile devices, tablets, and pretty much anything else.
The directory "notes/app
" contains the standalone application, which uses
HTML5 localStorage as a backing store. Some useful links to get you
started:
An alternative version of the application uses
MongoDB instead of localStorage
for notes data and
can be found in the "notes-rest
" directory. The application is
served via a Node.js/Express
application located in "notes-rest/server.js".
Although we don't provide an online demo application, the full application
test suite is available online using Sinon.JS
fake servers to fake out the requirement
of having a real backend MongoDB server for the App.Collections.Notes
tests. The test suite is nearly identical to the localStorage application tests
for all of the other tests.
The server requires Node.js and MongoDB installations. Once you have these installed, you can change into the root of this repository and install all of the project libraries:
$ npm install
To run the sample server application, you will need two terminal windows.
The binary mongod
must be available from the shell, so may need to
augment your PATH
variable. For example, on Windows, the following was
needed for some installations:
# May need to run console as Administator for just this command.
$ setx PATH "%PATH%;C:\Program Files\MongoDB 2.6 Standard\bin" /M
In the first window, start up MongoDB:
# Linux / Mac
$ npm run-script mongo-start
# Windows (with `mongod` available from `PATH`)
$ npm run-script mongo-start-win
In the second window, start up the Express server:
$ npm start
And from there you can navigate a browser to:
Note that you can control several application options by setting console environment variables:
MONGO_ADDR
: MongoDB host address (default 127.0.0.1
).MONGO_PORT
: MongoDB port (default 27027
).ADDR
: Express server host address (default 127.0.0.1
).PORT
: Express server port (default 4321
).For example, on a Mac:
$ export PORT=4323; npm start
runs the server on port 4323 instead of 4321 (the default).
The examples for each chapter are provided in the "chapters" directory, separated by number. We also provide a driver page for (nearly) all of the non-application tests.
Trying out the test libraries: Some first basic unit tests using Mocha, Chai, and SinonJS.
Test Failures: Different types of test failures.
Test Timing: Tests that take different times, which Mocha annotates for "medium" and "slow" tests. Also has one test timeout failure.
App.Models.Note
.BDD Interface: Tests using Mocha and Chai BDD styles.
TDD Interface: Tests using Mocha
TDD and
Chai assert
styles.
Chai Assertions: Tests using a variety of Chai BDD assertions.
chai-errors.spec.js: Exception handling.
Mocha only
: Tests using the Mocha
only
test modifier to run a single spec.
Mocha skip
: Tests using the Mocha
skip
test modifier to skip one or more specs.
Mocha Pending Tests: A basic skeleton suite with empty specs (e.g., no test callback), which are all in "pending" state during a test run. A great test development practice is to declare specs describing behavior without functions during the initial design phanse. The specs can later be implemented in parallel with the underlying application components, ensuring that the desired behavior is correctly implemented.
Tests: Continue tests for the Notes Backbone.js application.
App.Collections.Notes
.App.Views.NoteView
,
which renders model Markdown
data into HTML.Sinon.JS Spies: Various test uses for Sinon.JS spies.
Tests: Tests for the Notes Backbone.js application that use Sinon.JS spies.
App.Views.NoteNav
view, which mediates events for the single page navigation menu bar.App.Views.Note
view, which wraps all of the other single note views and model.Sinon.JS Stubs: Tests using Sinon.JS stubs.
Sinon.JS Mocks: Tests using Sinon.JS mocks.
Tests: Tests for the Notes Backbone.js application with Sinon.JS stubs and mocks.
App.Views.NotesItem
view, which displays a table row for a single note in the "all notes"
list.App.Routers.Router
router, implementing the route matching logic, but omitting the actual
view creation and display. The tests that we create a good starting point
for testing routers, but please see the Notes application source
for the
real App.Routers.Router
source
and full "routers/router.spec.js"
file.We don't introduce any new tests in Chapter 6, instead focusing on automating all of the application and chapter tests we have provided in this respository. See the next section for a discussion of test automation with PhantomJS.
All of the tests for the Notes application and the chapter samples can be run in the PhantomJS headless WebKit engine and/or any local browsers.
Simply install the Node.js dependencies:
$ npm install
which will place an internal PhantomJS binary in "./node_modules/.bin/phantomjs" as well as all other necessary libraries.
From there, you can use the mocha-phantomjs
binary to run any HTML test
driver page from the command line, e.g.:
$ ./node_modules/.bin/mocha-phantomjs notes/test/test.html
As a helper, the following script command will run nearly all of the Notes application and chapter unit tests:
$ npm test
Karma is a multi-browser command-line test runner. It can run tests from any combination of PhantomJS and any locally installed browsers (that have a Karma test runner implemented) -- like Chrome and Firefox.
We use a Grunt plugin grunt-karma
to help configure Karma for the tests in
this project. You can run all of the tests using PhantomJS alone in Karma
with the following command:
$ node_modules/.bin/grunt karma:fast
Alternately, you can switch to "development mode" which keeps the Karma test engine running (which we've configured to use PhantomJS, Chrome and Firefox) with:
$ node_modules/.bin/grunt karma:dev
This process then waits for test invocations, which you can do by opening a second terminal in the same directory and typing:
$ ./node_modules/.bin/karma run
This two-terminal approach saves you the overhead of firing up all of the browser environments in which to run the test suites.
We run all of these tests automatically using (the awesome) Travis CI continuous integration service. Travis watches the GitHub repository containing this project and when it detects the code has changed, launches new builds and invokes the PhantomJS tests above.
Travis even provides a convenient image status indicator, that we display below, so that we can display the always current build status of our code. Additionally, we run our Karma tests through a coverage reporter that uploads to Coveralls, so we have a coverage report as well:
Setting all of this up is as simple as adding a Travis configuration file ".travis.yml" as follows:
language: node_js
node_js:
- 0.10
This instructs Travis to test out the latest Node.js versions for v0.8 and
v0.10. By default, Travis already has PhantomJS installed and will run
npm install
and npm test
on any Node.js project, which conveniently
sets up and invokes all of our PhantomJS tests.
Our actual ".travis.yml" file runs different commands than
the default npm test
to add things like style checking. But, the overall
Travis configuration is essentially the same.
We also do multi-browser testing of the frontend code thanks to generous donations of VM time from Sauce Labs and BrowserStack. Here's our build matrix:
There are many additional testing libraries and plugins specifically suited to testing Backbone.js applications beyond the core test stack we use in the application and chapter examples above.
Chai has a rich plugin ecosystem, with libraries that enhance the core Chai assertion statement library, provide more specific failure messages, and make application behavior easier to express.
Plugins that are used in some examples:
expect(spy).to.have.been.calledWith(42)
instead
of the Sinon.JS native sinon.assert.calledWith(spy, 42)
.Additional plugins not used in the examples:
$class()
,
$attr()
, and $hidden
.data()
, class()
,
id()
, and hidden()
.expect(model).to.trigger()
and
expect("hash/fragment").to.route.to()
.All frontend libraries used in this repository for the sample apps and chapter examples are provided in the "vendor" directory.
Note that this repository has been updated since the publication of Backbone.js Testing on July 12, 2013. The enumerated versions of all third party libraries are indicated by the most current version in the repository with the published version noted in parenthesis when different.
The core Backbone.js components used are:
2.1.0
(2.0.2)1.6.0
(1.4.4)1.1.2
(1.0.0)1.1.7
(1.1.5)The sample Notes application also uses:
3.1.1
(2.3.2)0.3.1
The frontend test libraries we use are:
The test plugins include:
2.4.0
3.2.0
(2.0.3)The repository was tagged with git as published-1.0
for the code samples
that are shipped with the book as it went to press. To check out the published
version in this repository, type:
$ git checkout tags/published-1.0
This will switch all libraries, application code, and tests to the version that directly matches the book.
As of v3.x.x and higher, Mocha-PhantomJS requires PhantomJS v1.9.1 or higher.
Mocha version 1.10.0 and 1.11.0 introduced incompatibilities with Mocha-PhantomJS. Modern versions of both libraries are now compatible, e.g., Mocha v1.12.0+ and Mocha-PhantomJS v3.1.0+.
For this historically minded, the evolution of this issue is documented in the following tickets:
Backbone.js Testing shipped with Mocha v1.9.0 and Mocha-PhantomJS v2.0.3 to avoid the issue.
All code not otherwise specified is Copyright 2013 Ryan Roemer. Released under the MIT License.
This repository contains various libraries from other folks, and are licensed as follows:
Backbone.js is Copyright Jeremy Ashkenas and licensed under the MIT license.
Underscore.js is Copyright Jeremy Ashkenas and licensed under the MIT license.
jQuery is Copyright jQuery Foundation and licensed under the MIT license.
Backbone.localStorage is Copyright Jerome Gravel-Niquet and licensed under the MIT license.
JSON is Public Domain software created by Douglas Crockford.
Mocha is Copyright TJ Holowaychuk and licensed under the MIT license.
Chai is Copyright Jake Luer and licensed under the BSD license.
Sinon-Chai is Copyright Domenic Denicola and licensed under what we will politely approximate to a "public domain" license.
Sinon.JS is Copyright Christian Johansen and licensed under the BSD license.
Twitter Bootstrap is Copyright Twitter, Inc. and licensed under the Apache v2.0 license.
Jasny Bootstrap is Copyright Twitter, Inc. and Jasny BV and licensed under the Apache v2.0 license.
Showdown is Copyright Corey Innis and licensed under the BSD license.
Mocha-PhantomJS is Copyright Ken Collins and licensed under the MIT license.
Blanket.js is Copyright Alex Seville and licensed under the MIT license.
For those who would like to get under the hood, or help out with the application or test examples.
For pretty much everything, you will need to install a Node.js environment, and the development NPM dependencies:
$ npm install
From there, there are various Grunt script helpers for style checking and tests:
# Run style checks for server, client, and both.
$ node_modules/.bin/grunt jshint:server
$ node_modules/.bin/grunt jshint:client
$ node_modules/.bin/grunt jshint
# Run headless tests for the application, individual chapters, all chapters
# as one big test, and all of these together.
$ node_modules/.bin/grunt test:app
$ node_modules/.bin/grunt test:rest
$ node_modules/.bin/grunt test:chaps
$ node_modules/.bin/grunt test:chaps-all
$ node_modules/.bin/grunt test
# Run all style checks and headless tests.
$ node_modules/.bin/grunt check
The file "README.md" is transformed from markdown into the HTML page "index.html", and can be compiled once, or watched for changes with the following commands.
$ node_modules/.bin/grunt jade:docs
$ node_modules/.bin/grunt watch:docs
We internally use bower to get / upgrade our vendor libraries. To update these, do the following:
$ node_modules/.bin/bower install
$ node_modules/.bin/grunt build:vendor
We internall synchronize the notes
application and test files to notes-rest
,
overwriting the latter. To do this:
$ node_modules/.bin/grunt build:notes-rest
Note: This overwrites files in notes-rest
, so don't invoke this if
you intend to change those files!
Finally, we have a lot of other builds (templates, docs, etc), that are all aggregated as part of:
$ node_modules/.bin/grunt build
in addition to the tasks described above.
Bugs, issues and fixes for any of the application or test code examples are most welcome. Please file a GitHub issue or pull request for any changes. Pull requests should be able to pass
$ node_modules/.bin/grunt check
without any errors.
src
attribute link to TDD example test file. The Chapter 3 file
"tdd.spec.js" in the samples should have been named "tdd.js". The text of
the book remains correct - only the code sample has been updated.
(@aserputko)published-1.0
)