Getting started with Mocha

To use Mocha, you will first need to download the mocha.css and mocha.js files from the project's GitHub page (which can be found at https://github.com/mochajs/mocha). You will also need to download an assertion library; for this example, we'll be using Expect.js (which you can download from https://github.com/Automattic/expect.js).

Next, you will need to create a new HTML page and add script tags for all of your application's JavaScript files, as well as all library files (for instance, Backbone and jQuery). You'll also need to add a few bits of Mocha boilerplate code. All together you should wind up with an HTML file that looks something like the following:

<html>
<head>
<!-- External Library Files -->
<script src="/underscore.js"></script>
<script src="/jQuery.js"></script>
<script src="/Backbone.js"></script>

<!-- Application-Specific Files -->
<script src="/SomeModel.js"></script>
<script src="/SomeView.js"></script>
<script src="/SomeOtherNonBackboneCode.js"></script>

<!-- Test Library Files -->
<script src="/mocha.js"></script>
<link rel="stylesheet" type="text/css" href="/mocha.css"></link>
<script src="/expect.js"></script>
</head>
<body>
<div id="mocha"></div>
<!-- Test Code -->
<script>
mocha.setup('bdd'), // start Mocha in BDD mode
// *INSERT TESTS HERE*
mocha.run();
</script>
</body>
</html>

TDD versus BDD: What's the difference?

In the preceding code, we call mocha.setup (bdd), which starts Mocha in the BDD mode (as opposed to the TDD mode). But what does this even mean?

Test Driven Development (TDD) is a style of development where the developer begins all his work by writing a (failing) test case. The developer then adds just enough code to his application to make that test pass, but no more than that. As soon as the test passes, the developer writes a new (failing) test and repeats the cycle.

The advantages of TDD are two-fold. First, by always writing a test first, the developer guarantees that his code will always be completely covered by tests. Second, the TDD style naturally forces developers to write their code in a testable fashion, which means adopting practices like writing several short functions instead of one long one. As we mentioned in the previous chapter, these practices have benefits that go beyond the test environment.

However, TDD also has its downsides. Perhaps, the most significant one is that it can result in excessive, useless tests, which require significant time to maintain. Also, by its very nature, TDD focuses heavily on how the code does instead of what it does, but many programmers would argue that what the code does is far more important to test.

This distinction is particularly important when refactoring. By definition, a refactoring operation is required when you change how the code does what it does without changing what it does. Because TDD-based tests focus so heavily on the how, whenever a refactoring occurs, the tests need to be updated to match the new code.

Behavior Driven Development (BDD) is very similar to TDD but attempts to solve the problems related to TDD by focusing on what the code does. This is achieved largely by using a slightly more verbose syntax for organizing tests and test suites. Of course, one doesn't necessarily need a different syntax to write tests that focus on what the code does, but the benefit of the BDD syntax is that it naturally encourages such behavior.

Consider the following imaginary test of the Backbone set method of Model, written using Mocha's TDD syntax and the better-assert assertion library. It works by creating testModel, setting an attribute (a) with a value (1), and then confirming that the attribute/value pair has been added to the test attributes of Model:

suite('Model', function() {
    var testModel;
    setUp(function() {
        testModel = new Backbone.Model();
    });
    suite('set', function() {
        test('set adds a value to the model's attributes', function() {
            testModel.set('a', 1);
            assert(testModel.attributes.a === 1);
        });
    });
});

As you can see, in the TDD code, a test is registered using a test function and groups of tests are organized into suites. Also, the test verifies the validity of the code by using an assert statement. Now, let's look at a similar imaginary test created using the BDD syntax:

describe('Model', function() {
    var testModel;
    beforeEach(function() {
        testModel = new Backbone.Model();
    });
    describe('#set', function() {
        it('sets a value that "get" can retrieve', function() {
            testModel.set('a', 1);
            expect(testModel.get('a')).to.be(1);
        });
    });
});

Notice how similar the two tests are: While the first example uses suite and the second uses describe, both functions have the same effect of grouping tests. Similarly, in the BDD example, tests are still defined and still contain validity checks, but the tests are defined with an it function, and instead of assertions, we have expectations (expect calls).

However, there are two important differences that go beyond just the names of the functions. First, the latter example reads much more like an English sentence, making it easier to read both in the code, and later on, when viewing the test results. Second, and more importantly, the first test emphasizes how set works, while the second one emphasizes what it should do. While there is nothing inherent in either the TDD or the BDD style that forces either test to be written in a certain way, this example highlights how the syntax can nevertheless influence a test's design. This can become important later on if the Backbone developers ever change Backbone to use a different name instead of attributes, as they will then have to rewrite the first test while the second one would continue working without adjustment.

Ultimately it is possible to test what your code does with either style of test, and so, it's really just a question of which style you prefer. However, if you have no opinion one way or the other, the BDD syntax is probably a better starting point, both for its improved readability and for its natural emphasis on describing what the code should do. For these reasons, we'll continue to use the BDD syntax in the rest of this chapter.

Describe, beforeEach, and it

If you've used testing libraries in other languages before you might already understand the preceding code, but if not allow me to explain. The test starts with a call to Mocha's describe function. This function creates a suite (or grouping) of tests, and you optionally nest more describe functions to further organize your tests. One benefit of using describe statements is that when you go to run your tests, you can choose to only run a specific suite defined by describe, rather than running all of them at once. The describe function takes two arguments: a string indicating what is being described, and a function that is used to wrap all of the tests within the describe function.

Next, we have a beforeEach call that, as you might imagine, defines code that will run before each test. This can be a useful place to separate code that is common to all of the tests in the describe statement (such as the creation of a new Backbone.Model class in the preceding example). Mocha also has an equivalent afterEach function that runs similarly after each test completes and can be used to clean up the side effects of the tests. Mocha also has before and after functions, which are similar except that they only run once per describe statement (that is per suite), rather than once per test.

After another describe (this time to group tests related to set), we get to the it function, which actually defines a specific test. Like describe, it takes two arguments: a string that describes what it (the code being tested) should do, and a function that tests whether the indicated behavior is actually occurring. If the function passed to the it function completes without throwing an error, Mocha will consider this test to have passed, whereas if an error is thrown, it will instead mark that test as failed (and provide the stack trace of the thrown error in the test output so that you can easily debug the relevant code).

Finally, we have the expect function (which could just as easily be called assert or something else had we chosen a different assertion library). The expect function takes a single argument and then uses jQuery-like chaining to assert something about the first argument. Here are a few examples:

expect(1).to.be(1); // asserts that 1 === 1
expect(1).not.to.be(2); // asserts that 1 !== 2
expect(1).to.eql("1") // asserts that 1 == "1"
expect(1).to.be.ok(); // asserts that 1 is "truthy" (evaluates true when used as a boolean)
expect(1).to.be.a('number'), // asserts typeof 1 === 'number'

The Expect.js library has several other forms of assertions as well, all of which you can find detailed on their GitHub page.

Running our test

Now that we understand how everything works, let's try to actually run our test. To do this, simply replace the following line in our HTML file with the describe code provided earlier:

// *INSERT TESTS HERE*

Alternatively, you can also choose to put the describe code into a separate file and replace the insert line with a script tag that references this file. Either way, save the file and open it up in your favorite web browser. You should see something like this:

Running our test

Our test passes!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.238.82.77