Behavior Driven Development with Mocha and Chai

This article introduces the concepts of behavior driven development. Together we will configure a very basic Mocha test using the Chai framework.

Basic Vocabulary

As I first began to dive into this field, I noticed several closely related terms and tools which pop up frequently in reference material:

Test Driven Development (TDD) – This is the approach of  developing tests prior to writing production-ready code. With this philosophy code begins with the minimal viable functions required to produce the intended output and refactoring into production-ready code occurs later.

Behavior Driven Development (BDD) – Combines the general techniques of TDD and uses natural language constructs (English-like sentences) to express the behavior and expected outcomes of tests.

Mocha.js – A flexible Node.js based testing framework. Mocha is a popular choice for unit and integration testing in the console and the browser. Learn More.

Chai.js – A Mocha compatible assertion library, allowing for expect(), assert() and should-style assertions. Learn More.

Setting Up

Install both Mocha and Chai and add them into our package.json file:
npm install --save-dev mocha chai
It may also be worth installing mocha globally:
npm install --global mocha
If performing npm init, use this as an opportunity to set test command to mocha. Otherwise, manually add it to the scripts object in package.json. Also, set the watch condition to allow Mocha to run tests whenever files in our root directory are modified:
"scripts": {
"test": "mocha",
"test:watch": "mocha --watch ./test ./"
}

With Mocha set to the test trigger, we can now use the command npm run to run all tests in our test directory. With test:watch, we gain the ability for Mocha to automatically run our tests for us as soon as we save modify any file in our project.

You may notice we don’t yet have a test directory. We’ll make one now in our project root:

Inside that we’ll make a new file called core_tests.js

Testing 101

Software tests describe expected behavior without worrying how the code achieves it. Within each test file is a collection of one or more test suites. These test suites hold unit tests, known as specs, which are used to verify the functionality of a particular code block. And within the unit test specs are one or more assertions, which actually validate the resulting response from the code being tested. That hierarchy may take some getting used to. I built a quick diagram to help myself understand:

 

We can see this in action with a very basic test to serve as a sanity check to confirm that the basic connection works. For our sanity check, we can verify with an always-true statement:

// sanity check test
describe('Mocha sanity check suite'),function(){
    it('should run our test via npm', function(){
        expect(true).to.be.ok;
    })
}

The describe() method call of a test suite takes two arguments; a description string and an anonymous function. When used within the describe method, each spec should be wrapped in a method called it(), which also takes two arguments, one for a description of the intended behavior, and the second for a function containing the state condition for the test.

Please note that to implement this into a real project we’d need to import `expect` to leverage Chai’s assertion abilities. Here’s a more realistic code example:

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

describe('What area of code is the test suite targeting?',()=>{
    let someFunction = require('../controller/playerMethods').addContact; //import function to test
    it('What should the specific function do?',()=>{
        let contact = {
            name: 'Paul Atradies',
            phone: '305-123-4567',
        }
        addContact(contact) // 
        expect(contact[0]).to.not.be.empty; // test assertion
    })
})

Common assertion styles

Chai is a flexible assertion library. For Behavior Driven Development, it provides many types of assertions that can be used. A full list can be found here, but below are common methods:

  • Assert
    • assert.typeOf()
      • assert.typeOf(foo, ‘string’, ‘foo is a string’);
    • assert.equal()
      • assert.equal(foo, ‘bar’, ‘foo equal `bar`’);
    • assert.length()
      • assert.lengthOf(foo, 3, ‘foo`s value has a length of 3’);

Add a Comment

Your email address will not be published. Required fields are marked *