Writing tests in ES6 with Gulp, Mocha, Chai, and Babel 6.0.0

As there not nearly as much documentation about testing as there needs to be on the web I thought I would write about my experience setting up my Theorem Gulp project to use Babel 6.0.0 to write my Mocha, Chai tests using ES2015 (ES6). This article will contain detailed explanations of why things work and how as well as a TL;DR section.

TL;DR

First go to your package.json file and add the following packages under your devDependencies.

    package.json

{
  "devDependencies": {
    "mocha":"2.3.3",
    "chai":"3.4.0"
  }
}

  

So that now all together if you were following from the previous article. You should see a package.json file similar to below

    package.json
    
{
  "name": "theorem",
  "description": "A ES6 transpiled via Babel to ES5 library that adds methods to the Math class for working with JS.",
  "version": "1.1.0",
  "homepage": "https://github.com/aasierra/theorem",
  "author": {
    "name": "Anthony A Sierra",
    "url": "http://anthonysierra.com/"
  },
  "devDependencies": {
    "gulp-sourcemaps": "1.6.0",
    "gulp-concat":"2.6.0",
    "babel-preset-es2015":"6.0.14",
    "babel-plugin-transform-object-rest-spread":"6.0.14",
    "gulp-babel":"6.0.0",
    "gulp":"3.9.0",
    "mocha":"2.3.3",
    "chai":"3.4.0"
  }
}

After that is done you will want to setup a gulp test task that builds the code then the tests then runs the tests. Add these lines

  gulpfile.js
  
gulp.task('default', function () {//Use Babel 6.0.0 to transpile application code.
  return gulp.src("./src/*.js")
  .pipe(sourcemaps.init())
  .pipe(babel())
  .pipe(concat("all.js"))
  .pipe(sourcemaps.write("."))
  .pipe(gulp.dest("dist"));
});

gulp.task('buildTests', ['default'], function () {//Use Babel 6.0.0 to transpile test code.
  return gulp.src("./tests/*.js")
  .pipe(sourcemaps.init())
  .pipe(babel())
  .pipe(gulp.dest("built-tests"));
});

gulp.task('test', ['buildTests'], function () {
  var mocha = require('gulp-mocha');
  gulp.src("./built-tests/test.js", {read:false})
  .pipe(mocha({reporter:'nyan'}));
});

  

So as you can see we have 3 gulp tasks which can all be called from the command line but you will want to use gulp test which will transpile the code, transpile the tests, then run the transpiled tests.

Next create a tests folder in the root of your project and create a test file called test.js and add the below code.

  tests/test.js
  
let expect = require('chai').expect;
let assert = require('assert');
describe("Should return true", () => {
  it('should show true equals true', () => {
    assert.equal(true, true);
  });
});
  

Now that we have transpilation setup we can run gulp test and you should see a happy nyan cat and your generated dist and built-tests folders. You can see the actual changes to my Theorem project here to see a fully working code example.

Full explanation

So now let us talk about what was above because there is actually some very important points to look at. First I would recommend reading the previous article to get a full understanding and then reading this.

First lets talk about the packages we added. As you can see we simply added mocha and chai and nothing more. This is because we can simply make them run against the transpiled files for the tests. There is not a need to use some other type of runner, except maybe to increase build speed which arguably would make it slower. Anyways, I wanted to point out that there is no magic, just basic transpilation and running transpiled code.

Next we need to talk about the gulp tasks. This is VERY IMPORTANT! The tests will not run synchronously if you do not use the 3 argument call to the gulp.task method. You first specify the task name, array of tasks that need to finish, then function. The second argument however needs to be calling a task that returns the gulp stream. If you notice the buildTests task and the default task both return their gulp streams (gulp.pipe's return value). If you were to not return those values the methods would just execute asynchronously and your tests would run against nothing / old code.

Alright and the final thing I wanted to talk about is how to in this ES6 environment require code you are actually working on. So for an example let's use my Theorem library.

  tests/anotherTest.js
  
let GCD = require("../src/GCD.js");
let expect = require('chai').expect;
let assert = require('assert');
describe("Math GCD Should work", () => {
  it('should return 3 for 12 and 15', () => {
    assert.equal(Math.gcd(12,15), 3);
  });
});
  

As you can see above I am requiring a file directly instead of some sort of module. This is allowed. The code will be parsed and used. So this code below

  src/GCD.js
  
/**
This method find the greatest common denominator of two objects using the modules axiom.
@param {Number} The higher number a, of the two parameters where a > 0
@param {Number} The lower number b, of the two parameters where b > 0
*/
Math.gcd = function(a, b) {
  return b === 0 ? a : Math.gcd(b, a % b);
}
  

Is completely validly parsed and the test is able to simply use the Math.gcd function, if anything I do not even need the variable assignment to GCD.

Now if you wanted it so that the GCD variable above in anotherTest.js was usable you could add module.export = Math to the GCD.js file. That would allow you to call GCD.gcd instead of Math.gcd, but then that defeats the purpose of the test ;)

Anyways that is how you take your Gulp ES6 project and add Mocha and Chai tests to it. For a full working example you can checkout my Theorem project located here.