Tuesday, October 18, 2011

Taking Baby Steps with Node.js – BDD Style Unit Tests with Jasmine and CoffeeScript

< The list of previous installments can be found here. >

In a previous blog post, I already wrote about BDD style unit tests for testing Node.js modules using Jasmine. I really like the conciseness, simplicity and readability of specification style unit tests using Jasmine. But when we pour CoffeeScript into the mix, then the syntax for BDD style unit tests really starts to get interesting.

Here’s a simple example of a Jasmine test suite written in CoffeeScript:

{ BurglarAlarm, BurglarAlarmState } = require('burglaralarm')
ControlRoom = require('controlroom')
should = require('should')
sinon = require('sinon')

describe 'An armed burglar alarm', ->
    _sut = null

    beforeEach ->
        _sut = new BurglarAlarm()
        _sut.arm()

    describe 'When a break in occurs', ->
        beforeEach ->
            _sut.breakIn()

        it 'should indicate that there is a burglary', ->
            _sut.state().should.equal(BurglarAlarmState.alarm)

        it 'should trigger the siren', ->
            _sut.siren().isRinging().should.be.ok
    
    describe 'When there is being tampered', ->
        _mockedControlRoom = null

        beforeEach ->
            _mockedControlRoom = sinon.mock(ControlRoom.getInstance())
            _mockedControlRoom.expects('notifyTamperAlarm').once()
            
            _sut.tamper()
            
        afterEach ->
            _mockedControlRoom.restore()

        it 'should indicate that there is a tamper alarm', ->
            _sut.state().should.equal(BurglarAlarmState.tamper)

        it 'should notify the control room', ->
            _mockedControlRoom.verify()

 

Personally, I really like this syntax. Notice the destructuring assignment on the first line. This is a small trick we can use when a particular module exports multiple types. We also used a mocking library called Sinon.js which is a very powerful library for test spies, stubs and mocks for JavaScript.

Here’s the code for the BurglarAlarm, ControlRoom and Siren modules. Note that this example code is also written using CoffeeScript, but this can be plain old JavaScript as well if you want.

##############################################
# BurglarAlarm module
##############################################
BurglarAlarmState = 
    normal: 0
    armed: 1
    alarm: 2
    tamper: 3

exports.BurglarAlarmState = BurglarAlarmState

class exports.BurglarAlarm
    _siren = null
    _state = BurglarAlarmState.normal
    
    constructor: ->
        _siren = new Siren()    
        
    siren: -> _siren
    state: -> _state

    arm: -> _state = BurglarAlarmState.armed

    breakIn: -> 
        _state = BurglarAlarmState.alarm
        _siren.makeSomeNoise()    

    tamper: ->
        _state = BurglarAlarmState.tamper
        ControlRoom.getInstance().notifyTamperAlarm()

##############################################
# ControlRoom module
##############################################
class ControlRoom
    notifyTamperAlarm: ->
        console.log('Tamper alarm noticed in the control room ...')

instance = null

module.exports = {
    getInstance: ->
        unless instance?
            instance = new ControlRoom()
        instance
}

##############################################
# Siren module
##############################################
module.exports = class Siren
    ringing = false

    isRinging: -> ringing
    makeSomeNoise: -> ringing = true

 

There you go. Until next time.

Saturday, October 15, 2011

The Cathedral and the Bazaar

A couple of weeks ago, I ran into this website from Eric S. Raymond, the author of the book The Cathedral and the Bazaar. There’s a recording of a great presentation that anyone involved with software development, and especially open-source, should listen to. I highly recommended that you download this recording and at the very least listen to it twice! You can also read the book online.

Enjoy!