filipedeschamps / rss-feed-emitter

Super RSS News Feed aggregator written in Node.js and ES6

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

10. Create your first automated test to cover the public interface

filipedeschamps opened this issue · comments

Now things starts to become exciting. Understand how to do automated tests is a must if you want to consider yourself a good developer.

Assertion library

We are going to use Mocha as our test runner, but first we need an assertion library. An assertion library is responsible to compare values, for example, expect that variable A has the value X, and if it doesn't, throw an error to mark that test as failed.

We will use chai, which is one of the best in town:

$ npm install --save-dev chai

Test runner

Like said before, we will use Mocha to run our tests scenarios:

$ npm install --save-dev mocha

Unit tests

We are ready to write our first unit test. Our objective here is to ensure we are correctly creating an instance and it has all the public methods we coded before.

Create a file called test/unit/rss-feed-emitter.spec.js. Notice the .spec.js in it's name. This is a pattern and you will understand later what is used for.

So, import our own module to the test file:

'use strict';

import RssFeedEmitter from '../../src/rss-feed-emitter.js';

Now let's import Chai and use it's expect assertion function:

'use strict';

import RssFeedEmitter from '../../src/rss-feed-emitter.js';
import chai from 'chai';

let expect = chai.expect;

And we are ready to test the most basic thing: if we create and instance from our module, does it return an object as expected? Let's write a test for this scenario:

'use strict';

import RssFeedEmitter from '../../src/rss-feed-emitter.js';
import chai from 'chai';

let expect = chai.expect;

describe( 'RssFeedEmitter ( unit )', () => {

  describe( 'when instantiated', () => {

    let feeder = new RssFeedEmitter();

    it( 'should return an Object', () => {

      expect( feeder ).to.be.an( 'object' );

    } );

  } );

} );

So we expect that the instance feeder is an object. How can we run this spec to see the results?

Running tests

Since we wrote the source code and test in ES6, we need to tell Mocha to use a compiler (Babel) and you do this by passing some arguments to it:

We are going to run this a lot of times so it's better to create a npm script to easy access this command.

Edit your package.json and add a new line in the scripts session:

{
  "name": "repository-demo-github",
  "version": "0.0.1",
  "description": "This is a demonstration repository",
  "main": "index.js",
  "scripts": {
    "test-unit": "mocha --compilers js:babel-core/register test/unit/**/*.spec.js"
  },
  //...

See what we did there? Now, everytime you run this in your command line:

$ npm run test-unit

Npm will run mocha --compilers js:babel-core/register test/unit/**/*.spec.js

Let me explain this command:

  • mocha
    Binary that read and runs the tests.
  • --compilers js:babel-core/register
    Register Babel as a compiler
  • test/unit/**/*.spec.js
    The pattern Mocha will search for files. See the *.spec.js? We can now add other files inside the test directory and if they don't match the pattern, won't be executed as test specs.

Now, run the npm run test-unit script and you will see something like this:

image

Amazing! Let's write the rest of the assertions to ensure all public interfaces are there, for example, we expect that add method will be a function, right?

'use strict';

import RssFeedEmitter from '../../src/rss-feed-emitter.js';
import chai from 'chai';

let expect = chai.expect;

describe( 'RssFeedEmitter ( unit )', () => {

  describe( 'when instantiated', () => {

    let feeder = new RssFeedEmitter();

    it( 'should return an Object', () => {

      expect( feeder ).to.be.an( 'object' );

    } );

  } );

  describe( '#add', () => {

    let feeder = new RssFeedEmitter();

    it( 'should be a Function', () => {

      expect( feeder.add ).to.be.a( 'function' );

    } );

  } );

} );

Results in:

image

Let's add all public methods:

'use strict';

import RssFeedEmitter from '../../src/rss-feed-emitter.js';
import chai from 'chai';

let expect = chai.expect;

describe( 'RssFeedEmitter ( unit )', () => {

  describe( 'when instantiated', () => {

    let feeder = new RssFeedEmitter();

    it( 'should return an Object', () => {

      expect( feeder ).to.be.an( 'object' );

    } );

  } );

  describe( '#add', () => {

    let feeder = new RssFeedEmitter();

    it( 'should be a Function', () => {

      expect( feeder.add ).to.be.a( 'function' );

    } );

  } );

  describe( '#emit', () => {

    let feeder = new RssFeedEmitter();

    it( 'should be a Function', () => {

      expect( feeder.emit ).to.be.a( 'function' );

    } );

  } );

  describe( '#on', () => {

    let feeder = new RssFeedEmitter();

    it( 'should be a Function', () => {

      expect( feeder.on ).to.be.a( 'function' );

    } );

  } );

  describe( '#list', () => {

    let feeder = new RssFeedEmitter();

    it( 'should be a Function', () => {

      expect( feeder.list ).to.be.a( 'function' );

    } );

  } );

  describe( '#remove', () => {

    let feeder = new RssFeedEmitter();

    it( 'should be a Function', () => {

      expect( feeder.remove ).to.be.a( 'function' );

    } );

  } );

  describe( '#destroy', () => {

    let feeder = new RssFeedEmitter();

    it( 'should be a Function', () => {

      expect( feeder.remove ).to.be.a( 'function' );

    } );

  } );

} );

Results in:

image

Next step

11. Generate code coverage reports

coool