It’s not always easy to know if you’re writing good, robust code if you don’t have anyone looking over your shoulder and telling you how you could do things better.

This is where Codeclimate comes in to play!

Code Climate

Why Codeclimate?

Codeclimate links to your github account, and examines every commit you do, letting you know if your code got better, or worse.

Code climate dashboard

It attributes a grade to each one of your files and detects the different issues.

Code Climate rating page

Now that’s a good looking rating page.

 

CodeClimate also works with Ruby (detecting security issues too), PHP (beta) and Python (beta). And guess what, it’s completely free if you’re using public repositories!

Now this is where it gets really interesting: CodeClimate also allows you to keep an eye on your code test coverage. Unit testing your javascript is extremely important, and if you want to build robust scalable javascript application, you have to unit test. It can take some time to get used to Test Driven Development, but it will change your way of producing code. (Long story short you’ll start producing decent code).

Enough theory, let’s talk about the tools we’re going to use.

I don’t know about you, but I like when I only have to press one key and everything takes care of itself.

  • I personally use Gulp to automate my builds, uploads, and tests.
  • To run my tests I use Mocha. If you need to test DOM manipulations, you may want to look at something called PhantomJS, a headless webkit with a javascript API. To keep it simple we’ll just look at Mocha today.
  • For my test coverage reports (the amount of tested and untested code in my repository) I use Istanbul.

All of these services have gulp packages and work perfectly together. You can probably use other unit testing services, but I’ve found that these ones work great together.

Now, a little bit of code.

Let’s take a look at a little test example:

utils.js

/**
* Get event ID from URL provided
* @param {string} url
* @return {string | false}
*/
module.exports.getEventId = function (url) {
    var re = /[\D]*([\d]*)/g;
    return re.exec(url)[1] || false;
};

This function is supposed to return the id of a Facebook event from a URL provided by the user. We want to make sure we get the ID whatever the format of the URL provided is.

test.js

describe('Utils', function(){
  describe('getEventId', function(){
    it('should return the event ID', function(){
    	assert.strictEqual(false, utils.getEventId());
    	assert.strictEqual(false, utils.getEventId(''));
    	assert.strictEqual('736749926396099', utils.getEventId('736749926396099'));
    	assert.strictEqual('736749926396099', utils.getEventId('736749926396099/'));
    	assert.strictEqual('736749926396099', utils.getEventId('/736749926396099/'));
    	assert.strictEqual('736749926396099', utils.getEventId('/736749926396099'));
    	assert.strictEqual('736749926396099', utils.getEventId('/events/736749926396099'));
    	assert.strictEqual('736749926396099', utils.getEventId('/events/736749926396099/'));
    	assert.strictEqual('736749926396099', utils.getEventId('events/736749926396099/'));
    	assert.strictEqual('736749926396099', utils.getEventId('736749926396099/?sid_reminder=7661468456239235072'));
      	assert.strictEqual('736749926396099', utils.getEventId('https://www.facebook.com/events/736749926396099/?sid_reminder=7661468456239235072'));
    });
  });
});

This test function is just sending a bunch of URLs in different formats, checking if the right ID is always returned. If you’re not familiar with the Mocha syntax, take a look at their documentation

This is the “test” task of my gulpfile.js:

var gulp     = require('gulp'),
    mocha    = require('gulp-mocha'),
    istanbul = require('gulp-istanbul');
 
gulp.task('test', function () {
    .pipe(istanbul({includeUntested: true}))
    .on('finish', function () {
        gulp.src('./assets/js/test/test.js’)
          .pipe(mocha({reporter: 'spec'}))
          .pipe(istanbul.writeReports({
            dir: './assets/unit-test-coverage',
            reporters: [ 'lcov' ],
            reportOpts: { dir: './assets/unit-test-coverage'}
        }));
    });
});

Let’s take a look at what is happening here:

return gulp.src('./assets/js/*.js')

Make sure you include every single one of the javascript files of your project in this glob, but not the minified prod ones, or you may have weird results (more info on the glob syntax here).

.pipe(istanbul({includeUntested: true}))

Sending includeUntested:true to gulp-istanbul is important if you want the test coverage percentage to be calculated based on your entire codebase. (Otherwise you’re going to get a 100% code coverage and feel very good about yourself). There are other ways to achieve full test coverage, as listed in this stack overflow topic but I honestly think my solution is the simplest one.

gulp.src('./assets/js/test/test.js’)

This is the path to your JS test file (It also works if you have more than one, this is a simple example)

.pipe(mocha({reporter: 'spec'}))

Here you send the file through Mocha to run your tests. The reporter attribute is the way the results are going to show up in your console. There are many, you can choose the one you like the best on their website. There’s even one with a nyan cat, if you’re into that kind of things.

.pipe(istanbul.writeReports({
    dir: './assets/unit-test-coverage',
    reporters: [ 'lcov' ],
    reportOpts: { dir: './assets/unit-test-coverage'}
}));

The rest of the task is sending the mocha results to istanbul so it can write the code coverage report.

CodeClimate requires test coverage results to be written in lcov. Mocha does it just fine.

The last step is to send your test coverage file to codeclimate. I decided not to automate this part because I don’t want to send my file every time I run my test (They pretty much run whenever I save a file) but you can surely automate this part as well.

Setting up test coverage analysis on codeclimate:

It’s really easy, the steps are listed on their website:

JavaScript instructions
  • Install codeclimate’s NPM package
$ npm install -g codeclimate-test-reporter


  • Specifying your repo token as an environment variable, send lcov coverage data to the codeclimate npm script
    For example, if your coverage data resides in a “lcov.info” file:

 

CODECLIMATE_REPO_TOKEN=[your repository token] codeclimate < [path to your lcov.info]

That last command line can surely be automated after each test if you like. You’ll find your repository token in the settings of your app on Codeclimate.
Once you’ve uploaded your coverage file, you can go to your Codeclimate dashboard and see your test coverage results.

Test Coverage in code Climate

You should do better than that…

 

Now this screenshot is not really what you should aiming for. It is pretty hard to get a 100% code coverage result, but 25% really isn’t enough, I’m aware I still have some refactoring to do.

Your code repository will get a general GPA, and the little grey bar in the middle represents the test coverage. You even get badges that you can include in your github readme if you want to brag or motivate yourself to improve that test coverage.

Code Climate GPA

Nice GPA! Need to improve that test coverage though…

TL;DR: Code Climate is a great tool to quickly and easily keep an eye on the quality of your code. It taught me to think my code better to avoid duplications and complex functions. More than anything, it forced me to unit test my functions, helping me building better code and getting my mind around Test Driven Development. If you want to read more about TDD, this is a great book: http://tddjs.com/

Now go on, setup your Codeclimate account, write a couple lines in your gulpfile and happily look at your GPA getting better and better!