How to Create Data-Driven Tests with MochaJS

In this article I show you how to write data-driven tests using MochaJS.

Step 1. Clone the starter project

Use git to clone my starter repo into a new folder.

git clone https://github.com/mitchallen/autom8able-mochajs-starter.git mocha-data-driven

cd mocha-data-driven/

npm install

Run the default tests to make sure the install went okay:

npm test

Step 2. Define a sum function

Replace the contents of src/index.js with this code:

module.exports = sum = (a) => a.reduce((t, v) => t + v, 0);

This code takes an array of values (like [10,15,20,30]), adds them together and returns the result.

The values in the statement are as follows:

  • sum is the function name
  • a is the array of values
  • t is the running total each time reduce is called
  • v is the next value in the array
  • 0 zero is the starting value

The reduce method loops through the array of values. It passes the the current total (starting with the initial value of zero) and the next value from the array to the arrow function. The function then returns the total plus the current value (t + v). The retuned value will be the new value of the total (t) when the next value is passed into the function.

To keep things simple I left out code to verify each value is a number, etc.

Step 3. Write a data-driven test suite

Replace the contents of test/smoke-test.js with this code:

"use strict";

// require assert

var assert = require('assert');

// require the source module

const sum = require('../src');

describe('smoke test', () => {
  context('sum function', () => {
    [
      { values: [20,15], expected: 35 },
      { values: [20,35,40], expected: 95 },
    ].forEach( function( el ) {
        it(`should sum ${el.values} and return ${el.expected}`, done => {
        const total = sum(el.values)
        assert.equal(total, el.expected,
          'not the expected return value');
        done();
      });
    });
  });
});

The code wraps a MochaJS it method in a forEach call tied to a list of objects.

Each object contains two properties:

  • values - the values to be summed by the function being tested
  • expected - the expected result of summing those values

To add more tests all you have to do is add more objects to the list.

Step 4. Run the tests

Run the tests:

npm test

You should see a result like this:

  smoke test
    sum function
      ✓ should sum 20,15 and return 35
      ✓ should sum 20,35,40 and return 95

  2 passing (5ms)

Congratulations! You just wrote a set of data-driven tests!

Step 5. Add a failing test

Add a test to the middle of the list that will fail:

{ values: [20,15], expected: 35 },
{ values: [-2], expected: -200 },
{ values: [20,35,40], expected: 95 },

Save the file and and run the tests again.

Notice that that test fails, but it doesn’t break the loop. The remaining test in the list is also run:

 smoke test
    sum function
      ✓ should sum 20,15 and return 35
      1) should sum -2 and return -200
      ✓ should sum 20,35,40 and return 95

  2 passing (7ms)
  1 failing

  1) smoke test
       sum function
         should sum -2 and return -200:

      AssertionError [ERR_ASSERTION]: not the expected return value
      + expected - actual

      --2
      +-200

Fix the test by updating the expected result to -2. Run it again and all should pass.

Step 6. Add a test for an empty array

Add a test for an empty array of values:

{ values: [], expected: 0 },
{ values: [20,15], expected: 35 },
{ values: [-2], expected: -2 },
{ values: [20,35,40], expected: 95 },

When you run the tests again, notice a problem with the output:

✓ should sum  and return 0

The code isn’t very good at handling an empty array.

To fix that, change the it line to this:

it(`should sum ${(el.values.length > 0 ? el.values : 'an empty array' )} and return ${el.expected}`, done => {

If the length of the values array is zero, then a string is used instead of the values.

The results should now look like this:

  smoke test
    sum function
      ✓ should sum an empty array and return 0
      ✓ should sum 20,15 and return 35
      ✓ should sum -2 and return -2
      ✓ should sum 20,35,40 and return 95

  4 passing (10ms)

Exercise for the reader

Here are some exercises for the reader:

  • Add your own set of tests, doing things like mixing and matching positive and negative numbers, floating points, etc.
  • Update the sum function to handle strings, objects, nulls, etc.
  • Add tests for lists that include strings, objects, nulls, etc.

Troubleshooting

If you think a test is failing when it should pass, use a calculator to double check.

Conclusion

In this article you learned how to:

  • Define a sum function for testing that uses the reduce method
  • Create multiple tests from a set of data
  • Handle a special situation when an array is empty

References

  • JavaScript reduce function [1]



About the Author

Mitch Allen tests cloud services for a robotics company in New England.