Getting Started Testing With Mocha

This is part of our series on getting started doing test-driven development in React.  Mocha is a test runner that you will typically use with an expectation library like chai

Mocha has really great documentation so I recommend reading those for a solid foundation. This short overview will help you get started quickly.

Configuration

Add the testing framework to your package.json:

 $ npm install --save-dev mocha

Add mocha to your package.json script “test” key

"scripts": {
  "test": "mocha spec"  // your tests should live in one folder named 'spec' or 'test'
}

Command to run tests:

$  npm test

Mocha provides the following:

  1. Functional blocks that write and group our tests;
  2. Setup and teardown input from plugins and other imported modules;
  3. Our assertions of the system under test.

You can use  describe or context to describe contexts— if you’ve used an object oriented test framework, like JUnit or PyUnit, this will help to define the class scope of your tests.

Secondly, it will allow you to define your test.  In an object-oriented framework, this will be like your test method.  For users of tools like rspecfor ruby, this pattern should be very familiar.

The TDD Cycle

The Test-driven development cycle is often referred to as “red, green, refactor.” Here’s how we implement it.

1) Red: refers to a test that has been constructed with an expectation of an output & no input. In doing this we created a failing or ‘red’ test.

var expect = require('chai').expect; // you need an assertion library like ‘chai` or `expect` to do much of anything with mocha (though you can just use if-statements and exceptions to get started).

describe('sum function', function() {
  it('adds two inputs', function() {
    //test should be written within the 'it' block
  });
});

In the above code we have created the framework for the test. We have an it function block within a describe block.

Within theitblock, we will use our assertion library to write an expectation we have about the result of the function we wish to create.

Adding our assertion begins the TDD cycle, as we should expect this test (or expectation) to fail. Say we have a file math_spec.js that actually tests our sum function:

var expect = require('chai').expect;

describe('sum function', function() {
  it('adds two inputs', function() {
    expect(sum(4, 8)).to.equal.(12);
  });
});

The next step is to create a passing or ‘green’ test, which we will do by providing what the test requires to pass. In our example, we would run the test file $ mocha math_spec.js.The console should then output an error:

ReferenceError: sum is not defined.

Using the error output from the test as a guide, we will define the sum function. Create a file called ‘math.js’ that will contain only the sum function (for now we will use node’s commonjs module system):

function sum(a, b) {
  return a+b;
};

module.exports = sum;

Now that we have written our code, let’s pull it into the test.

//math_spec.js

var expect = require('chai').expect;
var sum = require('../sum');

describe('sum function', function() {
  it('adds two inputs', function() {
    expect(sum(4, 8)).to.equal.(12);
  });
});

2) Green: Running the test passes, and the next step would normally be to refactor or to create another expectation (failing test) and continue building your code. Our example was simple, and more than likely the code for your app/project will be more complex, with behaviors that are typically more difficult to test.

When this is the case, you want to use test-doubles that can do things like ‘spy’ and record the behaviors of your functions. That can replace your function to different degrees and return values that you program. Test-doubles can also imitate the behavior of an ajax call and the server response, allowing you to test functionality without configuring and running a server to ensure that your code works properly. We will be adding more about asynchronous testing in later posts.

3) Refactor: At this point complex code examples may require simplification.  Clean up the code and make it concise, readable, and fluent . If the test turns red, correct the error until the example works as expected.  If additional specification is discovered, repeat the cycle to ensure that additional cases are accounted-for.

That’s red-green-refactor in a nutshell. We will be posting more on additional testing frameworks like karma-mocha and mocha-webpack as we continue our series on test-driven-development in React.

Leave a Reply