Setting up and writing our first tests
Now that we have the base test libraries, we can create a test driver web page that includes the application and test libraries, sets up and executes the tests, and displays a test report.
Tip
Downloading the example code
The source code for all snippets and code examples in this book is available online. Files and tests for each chapter can be found by number in the chapters
directory. See the Preface for download locations and installation instructions.
The examples are best used as a helpful check on your own progress after a chapter has been finished and you have applied the lessons and exercises to your own code and applications. As a gentle admonition, we encourage you to resist the temptation to copy and paste code or files from the examples. The experience of writing and adapting the code on your own will allow you to better internalize and understand the testing concepts needed to become an adept Backbone.js tester.
The test driver page
A single web page is typically used to include the test and application code and drive all frontend tests. Accordingly, we can create a web page named test.html
in the chapters/01/test
directory of our repository starting with just a bit of HTML boilerplate—a title and meta
attributes:
<html> <head> <title>Backbone.js Tests</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
Then, we include the Mocha stylesheet for test reports and the Mocha, Chai, and Sinon.JS JavaScript libraries:
<link rel="stylesheet" href="js/lib/mocha.css" /> <script src="js/lib/mocha.js"></script> <script src="js/lib/chai.js"></script > <script src="js/lib/sinon.js"></script>
Next, we prepare Mocha and Chai. Chai is configured to globally export the expect
assertion function. Mocha is set up to use the bdd
test interface and start tests on the window.onload
event:
<script> // Setup. var expect = chai.expect; mocha.setup("bdd"); // Run tests on window load event. window.onload = function () { mocha.run(); }; </script>
After the library configurations, we add in the test specs. Here we include a single test file (that we will create later) for the initial test run:
<script src="js/spec/hello.spec.js"></script> </head>
Finally, we include a div
element that Mocha uses to generate the full HTML test report. Note that a common alternative practice is to place all the script
include statements before the close body
tag instead of within the head
tag:
<body> <div id="mocha"></div> </body> </html>
And with that, we are ready to create some tests. Now, you could even open chapters/01/test/test.html
in a browser to see what the test report looks like with an empty test suite.
Adding some tests
While test design and implementation is discussed in far more detail in subsequent chapters, it is sufficient to say that test development generally entails writing JavaScript test files, each containing some organized collection of test functions. Let's start with a single test file to preview the testing technology stack and give us some tests to run.
The test file chapters/01/test/js/spec/hello.spec.js
creates a simple function (hello()
) to test and implements a nested set of suites introducing a few Chai and Sinon.JS features. The function under test is about as simple as you can get:
window.hello = function () { return "Hello World"; };
The hello
function should be contained in its own library file (perhaps hello.js
) for inclusion in applications and tests. The code samples simply include it in the spec file for convenience.
The test code uses nested Mocha describe
statements to create a test suite hierarchy. The test in the Chai
suite uses expect
to illustrate a simple assertion. The Sinon.JS
suite's single test shows a test spy in action:
describe("Trying out the test libraries", function () { describe("Chai", function () { it("should be equal using 'expect'", function () { expect(hello()).to.equal("Hello World"); }); }); describe("Sinon.JS", function () { it("should report spy called", function () { var helloSpy = sinon.spy(window, 'hello'); expect(helloSpy.called).to.be.false; hello(); expect(helloSpy.called).to.be.true; hello.restore(); }); }); });
Not to worry if you do not fully understand the specifics of these tests and assertions at this point, as we will shortly cover everything in detail. The takeaway is that we now have a small collection of test suites with a set of specifications ready to be run.