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:
- Functional blocks that write and group our tests;
- Setup and teardown input from plugins and other imported modules;
- 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 rspec
for 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.
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 the it
block, 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 common.js 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);
});
});
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.
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.