Sunday 26 April 2015

Use Jasmine to Run Tests as Part of the Grunt Process

I've been using Jasmine to runt Unit tests for a while now, but I've always triggered them manually through WebStorm. This is fine as long as I remember to trigger them, which most of the time I don't. I've recently started a new project at work and have been able to define a new process as part of it. This has been a great opportunity for us to learn from the mistakes that we've previously made and think about how we can try to avoid them this time. As part of this we've decided to build our unit testing into our development process. We've set it up so that if our tests don't pass, then the code doesn't get published to the output file and therefore can't be loaded into the browser. Using watch to chain our tasks means that we know the moment we've saved our files whether or not our code works as we want it to.

Downloading Jasmine and Dependancies

For Grunt to run Jasmine I've been using grunt-contrib-jasmine. To install this, on the command line, you need to navigate to the root of your project and run:

npm install grunt-contrib-jasmine

You may find that you struggle to download this due to it's dependancy upon phantomjs. Sometimes I've seen that this doesn't want to download, and I think that it's because the file name's length becomes too long. If this happens install phantomjs through npm and then install grunt-contrib-jasmine.

In order for grunt-contrib-jasmine to successfully run tests for AngularJs code then you need to install angular mocks. grunt-contrib-jasmine also needs to know about AngularJs itself (that's a dependancy of the code you're testing), and since AngularJs split out angular-route that also needs to be included in your project. I download all of these using npm for ease of referencing in my Gruntfile.

npm install angular
npm install angular-route
npm install angular-mocks

Configuring Jasmine in Grunt

In order for Grunt to run grunt-contrib-jasmine you need to configure it within your Gruntfile.

jamsine: {
    dist: {
        src: 'scripts/**/*.js',
        options: {
            specs: 'scripts/**/*.spec.js',
            vendor: ['node_modules/angular/angular.js',
                'node_modules/angular-route/angular-route.js',
                'node_modules/angular-mocks/angular-mocks.js']
,
            summary: true
        }
    }
}

In this example dist is the profile of your application.

The first property, src, is the location of the code files that you want to be tested. **/*.js means to look in any folder for any file that ends with the .js file extension. I also use a version of this in options.specs, which tells grunt-contrib-jasmine where to look for the code files that contain the tests themselves. In this case I tell it to look in any folder for any files that end with .spec.js. This is the pattern recommended by John Papa in his style guide of including the specs in the same folder as the code they're testing and naming them in the same way, with the extra .spec inserted. So for a file name controller.js I have a test file named controller.spec.js.

options.vendor provides grunt-contrib-jasmine with the location of any libraries that your code depends upon. For AngularJs these are the files that we downloaded earlier. The order that these files are listed is important as it is the order that grunt-contrib-jasmine loads them so you must be mindful of the order of dependancies. I've also set options.summary to true so that grunt-contrib-jasmine displays the error messages of any failed tests, which is helpful when trying to debug.

Once you've configured you need to load the npm in the standard way within the module.exports function:

grunt.loadNpmTasks('grunt-contrib-jasmine');

If you're going to let another task (like grunt-contrib-watch) run this then you don't need to register it, but if you want to run it yourself from the command line then include:

grunt.registerTask('default', ['jasmine']);

Now you can run grunt-contrib-jasmine from the command line in the root of your project by running:

grunt jasmine

No comments:

Post a Comment