Feb 9, 2012

Testing CoffeeScript with Mocha

Mocha is a flexible and feature-rich test framework for JavaScript created by the insanely prolific open-source developer TJ Holowaychuk. It's used to test some prominent projects in the Node.js ecosystem, including Connect and Express.

If you already have CoffeeScript installed (you do, don't you!? if not get it now), giving Mocha a try couldn't be easier. The clean, elegant look of nested callback functions in CoffeeScript, combined with Holowaychuk's awesome Should assertions, make CoffeeScript + Mocha the best-looking implementation of BDD that I have ever seen. Now, good looks aren't everything, but if they make you want to write a lot more tests, they can't be bad. (A word of caution: While Mocha works beautifully in the browser, Should does not, so for browser tests you'll need to use an alternate assertion library, such as Expect. Update: Chai provides an implementation of should assertions that works in the browser.)

Enough talk, let's look at a simple Mocha test in the BDD style.

describe 'Array', ->
  describe '#indexOf()', ->
    it 'should return -1 when not present', ->
      [1,2,3].indexOf(4).should.equal -1

Here is how to run the example:
  1. Install Mocha (globally for convenience): $ sudo npm install -g mocha should
  2. Copy the code above to array-test.coffee.
  3. $ mocha array-test.coffee --require should
As you can see, Mocha can compile and execute CoffeeScript directly when run in Node.js (browser usage requires compilation to JavaScript.) Even your production files can be in CoffeeScript. I created a simple mocha-coffeescript-boilerplate project on GitHub to illustrate this and get you started.

Coming soon on CoffeeScript Love: How to integrate Mocha browser tests with the Rails (>= 3.1) Asset Pipeline. Update: Read Testing CoffeeScript in Rails.

8 comments:

  1. Running into problems trying to test with coffeescript. Running tests on Javascript files succeeds though. Get the following on attempting to run mocha with coffeescript files.

    SyntaxError: Unexpected string
    at Module._compile (module.js:429:25)
    at Object..js (module.js:459:10)
    at Module.load (module.js:348:31)
    at Function._load (module.js:308:12)
    at Module.require (module.js:354:17)
    at require (module.js:370:17)
    at /home/sameet/testcode/coffeepress/node_modules/mocha/bin/_mocha:261:27
    at Array.forEach (native)
    at load (/home/sameet/testcode/coffeepress/node_modules/mocha/bin/_mocha:258:9)
    at Object. (/home/sameet/testcode/coffeepress/node_modules/mocha/bin/_mocha:249:1)
    at Module._compile (module.js:441:26)
    at Object..js (module.js:459:10)
    at Module.load (module.js:348:31)
    at Function._load (module.js:308:12)
    at Array.0 (module.js:479:10)
    at EventEmitter._tickCallback (node.js:192:40)
    make: *** [test] Error 1

    ReplyDelete
    Replies
    1. Which version of Mocha do you have? Do you have CoffeeScript?

      I'll get the latest version today and try for myself, I guess this might be a regression in Mocha though it doesn't seem likely. You might open a Mocha issue on GitHub.

      Delete
    2. mocha array-test.coffee -r coffee-script

      This worked form me:)

      Delete
    3. I'm getting output equivalent to Anonymous, above.

      CoffeeScript 1.2.0, mocha version 1.0.3, should 0.6.3, npm 1.1.2

      Jeffs-Work-iMac:dojo_poc jeffdickey$ mocha array-test.coffee --require should

      /Users/jeffdickey/src/rails/dojo_poc/array-test.coffee:2
      describe 'Array', ->
      ^^^^^^^

      node.js:201
      throw e; // process.nextTick error, or 'error' event on first tick
      ^
      SyntaxError: Unexpected string
      at Module._compile (module.js:432:25)
      at Object..js (module.js:462:10)
      at Module.load (module.js:351:31)
      at Function._load (module.js:310:12)
      at Module.require (module.js:357:17)
      at require (module.js:373:17)
      at /usr/local/lib/node_modules/mocha/bin/_mocha:273:27
      at Array.forEach (native)
      at load (/usr/local/lib/node_modules/mocha/bin/_mocha:270:9)
      at Object. (/usr/local/lib/node_modules/mocha/bin/_mocha:261:1)
      at Module._compile (module.js:444:26)
      at Object..js (module.js:462:10)
      at Module.load (module.js:351:31)
      at Function._load (module.js:310:12)
      at Array.0 (module.js:482:10)
      at EventEmitter._tickCallback (node.js:192:40)

      And it sucks with a very hard vacuum that any HTML to aid formatting is disallowed; no TT, PRE or DIV allowed. There's a fine line between being functional and being paranoid; this isn't even in the same timezone.

      Delete
  2. make sure you've got coffee-script as a dependency (a devDependency will do)...

    ReplyDelete
  3. Installing `mocha` and `should` might not go so easily for you; if Jade breaks, see this comment I made on an `npm` issue, where I documented the process that worked for me.

    ReplyDelete
  4. Mocha doesn't automatically handle coffeescript out of the box any more. So now you need to do this:

    mocha array-test.coffee --require should --compilers coffee:coffee-script

    ReplyDelete
  5. @Anonymous (2012-03-30):

    Sheldon's answer worked for me. So did this:

    mocha array-test.coffee -r coffee-script -r should

    ReplyDelete