This is Part 4 is my series on using Gulp with Visual Studio. So far we’ve covered setting up Visual Studio for use with Gulp, processing SASS, and getting the files ready for deployment.

In this post I want to talk about JavaScript code quality.

Code quality: tests and linting

JavaScript is a notoriously quirky language –  the tricky “this” operator, lack of block level scoping, the ability to use variables before declaring them, “==” vs “===”, etc etc.

We can do a number of things to tighten up our code quality. We can run tests to ensure our code works as expected, and we can run a linting program to catch any syntatic mistakes before running our code. Combining this with Gulp gives a nice workflow for development.

Linting with JSHint

Linting is a process of running a program to analyse code for potential problems, catching bugs before the program gets executed. Douglas Crockford created JSLint in 2011, and of course there is a gulp plugin for it. However, I prefer to use JSHint – a community offshoot of JSLint that allows for more customisation and is slightly more relaxed in its defaults. You can find a good comparison of the two here.

First, I would seperate out any third-party libraries or frameworks you have into their own folder(s). In my opinion this is good practice anyway, but especially if we are running linting – we don’t want failures on code we haven’t written! Next, we want to add the plugin to our package.json:

{
  "scripts": { "install": "echo Done" },
    
  "devDependencies": {
    "gulp": "~3.9.0",
    "gulp-load-plugins": "~0.10.0",
    "gulp-jshint": "~1.11.2",
    // other plugins here
  } 
}

Then, add the Gulp task to our gulpfile:

var sources = ['./Scripts/*.js', '!./Scripts/libs/*.js'];

gulp.task('watch-lint', function () {
    gulp.watch(sources, ['lint']);
});

gulp.task('lint', function () {
    return gulp.src(sources)
        .pipe(plugins.jshint({
            strict: true,
            predef: [""]
        }))
        .pipe(plugins.jshint.reporter('default'))
        .pipe(plugins.jshint.reporter('fail'))
    ;
});

Here’s a line by line breakdown of the important stuff:

  • Line 1: Define the JavaScript files we want linting, excluding any third party libraries and frameworks
  • Line 3-5: Set up a watch to run the linting task whenever we make a change to our JavaScript
  • Line 7: Set up our linting task
  • Line 8-12: Send our files to JSHint. JSHint has a number of options you can set to define how lenient or strict you want it to be. You can look at the docs to get an idea of what you can set. Here I’m only using the strict option (here is a good blog explaining strict mode). There is also a section to define any global variables you’re using that should be ignored – for example if you’re using Angular you’ll want to add “angular” here
  • Line 13-14: Send the output of the linting to some inbuilt reporters – one to output the results to console and one to raise an error for any failures

Now we can add the watch task to our default task, and we’ll have linting every time we change our code.

Tests with Karma

One of the great things about Gulp is that you can get a Gulp task to run other Node based packages directly. For example, you can run Karma within a task, without having to use a plugin. Combined with PhantomJS, a headless browser, you get a great unit testing framework for your JavaScript. First, add the packages:

{
  "scripts": { "install": "echo Done" },
    
  "devDependencies": {
    "gulp": "~3.9.0",
    "karma-jasmine": "~0.3.6",
    "karma": "~0.13.9",
    "karma-phantomjs-launcher": "~0.2.1"
    // other plugins here
  } 
}

Then, we’ll need to add our karma config file (karma.conf.js) at the root of the project :

module.exports = function (config) {
    config.set({
        files: ['./Scripts/*.js',
                './Scripts/Specs/**/*.js',
        ],

        exclude: ['./Scripts/libs/*.js'],

        frameworks: ['jasmine'],

        autoWatchBatchDelay: 1000,

        reporters: ['progress'],

        browsers: ['PhantomJS']
    });
};

One thing I’ve found using Karma in Visual Studio: often Karma can crash in Visual Studio with an “EBUSY” error. I haven’t found an adequate explanation for this yet – I think it’s because when you modify and save a file Visual Studio writes a temporary file to replace the file you are saving, which doesn’t sit well with Node. This can be mitigated by setting the “autoWatchBatchDelay” to 1000, which waits 1 second after any change before running tests.

Finally, our gulp task:

var Server = require('karma').Server;

gulp.task('runTests', function () {
    new Server({
        configFile: __dirname + '/karma.conf.js',
        singleRun: false
    }).start();
});

Here, we are simply firing up Karma from within a Gulp task and passing in our karma config file. We are also telling Karma to watch our files for any changes and re-run our tests if they change. If you are going to run this task on a build server (and you should), you’ll need to configure the singleRun variable here. This can be done by using yargs to pass in a variable to switch this behaviour.

There we are! There is a commit of all the changes here, which includes a sample test. I highly recommend using both linting and unit tests when writing JavaScript code, and Gulp is great at running these tasks for us.

Next, in the last past I want to share my thoughts on Gulp, specifically within the .NET ecosystem.

SHARE IT:

Leave a Reply