10Jul

Using grunt.js’s server with Mocha and Zombie

Posted by Elf Sternberg as Uncategorized

If you ever want to start unit testing your project, here’s a straightforward framework for doing so. ¬†First, create a simple Mocha unit test to access your home page. I’m going to use mocha, chai, and zombie. Note that I’m embedding– sorry about this– the target URL, but the location for it will be localhost for the time being. Chai adds some nice features to Mocha, such as the ‘should’ interface.

chai = require('chai')
chai.should()
zombie = require('zombie')
browser = new zombie.Browser()

describe 'Initialization', ->
    it 'should load the home page', (done) ->
        browser.visit 'http://127.0.0.1:8081/index.html', (error, browser, status) ->
            if error then console.log(error)
            browser.text('title').should.be.equal('Priority / Ignore')
            done()

Secondly, add a script to your grunt.js to call this from within Mocha. I put my tests in the path test/, so in my gruntfile I define the following task:

    mocha: {
        src: ['test/*_mocha.coffee']
    },
/* ... */
    grunt.registerHelper('mocha', function(command, test, done) {
        var args = {
            cmd: 'mocha',
            args: ['--compilers', 'coffee:coffee-script', '-R', 'xunit', '-C', test]
        };

        grunt.utils.spawn(args, function(err, result) {
            if (err) {
                console.log(err.stderr)
                done();
                return;
            }
            fs.appendFileSync('tmp/results.xml', result.stdout);
            done();
        });
    });

    grunt.registerTask('mocha', 'Run Mocha Tests', function() {
        var done = this.async(),
            task = this.name,
            sources = grunt.file.expandFiles(grunt.config([this.name, 'src'])),
            dest = grunt.config([this.name, 'dest']);

        sources.sort();
        grunt.file.mkdir('tmp');
        fs.writeFileSync('tmp/results.xml', '');
        async.forEachSeries(
            sources, 
            function(path, cb) { 
                grunt.helper('mocha', grunt.config([task, 'cmd']), path, cb);
            },
            done);
    });

My mocha scripts are in coffeescript, so I run mocha with the “use coffeescript” argument, as well as xUnit and “no color” output.

It’s now possible to run this script:

grunt server mocha

will run the grunt server, which you should have configured to point to your distribution directory, and then run the mocha script which will attempt to access the page, interpret it with zombie, and in this case verify that the title is what I expect it to be. ¬†Grunt’s static server will terminate automatically when the tests are completed.

I do it this way because my web applications are often amalgamations of many different sources: Less files processed with Recess, Coffeescript, Require.JS optimized sources, HAML, even HAML-to-HTML-to a JS template function wrapped in Require.JS’s define(). Much modern development is like this now, and having a solid set of unit tests that can assert your pages contain what you expect and behave as you anticipate is critical. Zombie is no substitute for in-browser testing, but it’s a hell of a good start.

Still, I can’t help but feel that it would have been quicker to write the grunt layer in a Makefile.

2 Responses to Using grunt.js’s server with Mocha and Zombie

jason

July 12th, 2013 at 3:50 pm

Whoa. I was literally doing this exact same thing two days ago (July 10) but with Phantom instead of zombie. I got pulled off until today on unrelated project issues but your timing is awesome. This could help solve some of the ‘no following ajax’ SEO issues that I’ve been having by hosting a static site.

Thank you for posting!

Elf Sternberg

August 26th, 2013 at 10:20 am

@jason: Sadly, I’ve been hired! This means I don’t get to play with the state of the art, but instead whatever they have, and sneak in side projects when I have spare time. Since I have two teenagers, I never have any spare time. I’d love to find a reason to test using Phantom; I tried for an afternoon but the internals weren’t sticking in my brain. I’ll give it another go later.

Comment Form

Subscribe to Feed

Categories

Calendar

July 2012
M T W T F S S
« Jun   Aug »
 1
2345678
9101112131415
16171819202122
23242526272829
3031