How to make node.js, CoffeeScript and Jasmine play nice with Vim

In order to see how much fun it could be to develop a web application BDD style, I decided to re-implement the node-chat sample application.

I started by implementing the chat server which runs on node.js, so making my chat server run on node.js as well was an easy decision. Why I used CoffeeScript over just Javascript  and Jasmine for testing will be explained below.

Although I will blog about the resulting implementation and specs separately, the impatient can go here to have look.

CoffeeScript

Everyone loves nice and quiet and for a lot of people that extends to their work environment; ergo we don’t like noisy code.

I believe in the idea of cleanly formatted code to make it more readable and that these clues are enough for a parser to deduce what I am trying to say. Curly braces make code less readable IMO and are not really necessary.

CoffeeScript takes this to heart.

It is a language that generates Javascript code. The generated code is as readable as Javascript allows, but at least I don’t have to look at it all day.

It borrows ideas from a number of languages and combines the best of each into a super succinct and expressive language. Ruby developers will feel right at home and some things like list comprehensions are reminiscent of Haskell.

Like Haskell and Python, CoffeeScript is whitespace sensitive and thus doesn’t need any extra information about the code structure aka noise.

CoffeeScript and Vim

In order to quickly compile and then run my coffee scripts with node, I looked for nice Vim integration and found it here.

Although the site explains how to use it, I will point out the usage scenarios that I found most important.

Auto-Compilation

Setup Vim to auto-compile coffee files when they are saved via:

  autocmd BufWritePost *.coffee silent CoffeeMake! -b | cwindow

This is super useful as now I can save my file and run it right after via node.

If there are any compilation errors, they will be shown in a separate window, which disappears only after the errors were resolved and the file is saved again.

Leave off the "!" in order to have the cursor jump to the line of the error automatically.

Coffee-Compile

This feature is probably most important, if you are like me new to both CoffeScript and Javascript.

It allows compiling the entire Vim buffer or the selected text only and shows the resulting Javascript right inside Vim.

I used it a lot when I wasn't sure if the CoffeeScript would do what I expected and to just get an idea of what it would look like in Javascript.

It is so easy to select a few lines of code, run CoffeCompile and watch and learn as the screenshot shows.

Jasmine

Jasmine is a BDD framework for Javascript, which means you can author your tests in CoffeeScript as well of course. In order to test code running in node.js, you will need jasmine-node. Install it via

npm install -g jasmine-node

For my project I placed my specification files inside the /spec folder and could immediately run them via

jasmine-node spec

Well almost at least. The site warns:

your specifications must have 'spec' in the filename or jasmine-node won't find them!

My file was called server_specs.js (after the CoffeScript compile step) and Jasmine still didn't find it. Turns out that renaming it to server_spec.js did the trick.

So be aware:

In order for Jasmine to find your specification files they need to end with spec.js.

Why I didn't use vows

This is a good time to mention that I gave vows a try first because it seemed to be so very much in vo(w)gue.

It's strong point for some and weak point for others - like me, is, that it runs all tests in parallel.

This is surely a good idea, but makes re-using things like stubs very hard, especially if you use a lot of child contexts like me. Tests start to affect each other in weird ways and it is very hard to keep them separate. As far as I understand, anything that is to be truly isolated needs to be returned by the "topic" and this becomes a nuisance once you have a lot of things that are affected by setting up a context.

I dabbled with it for a few hours until I decided the hoops I had to jump through weren't worth it - after all if I wanted to jump through hoops in order to test my code, I could just stick with static languages, right?

I found that I wasn't the only one who feels that way. When I looked around for alternatives, I found this on the nodeunit site:

While running tests in parallel seems like a good idea for speeding up your test suite, in practice I've found it means writing much more complicated tests. Because of node's module cache, running tests in parallel means mocking and stubbing is pretty much impossible.

I also think that running tests in parallel is more important if you are dealing with long running integration tests. IMO in that case it is better to separate these from the faster running unit tests and run them only once a day or so.

Jasmine and Vim

Although it could be perfectly sufficient to just save you file after you made some change and then switch to the terminal in order to run the tests, it definitely gets in the way of the red - green - refactor workflow.

I prefer to just have to hit one shortcut key in order to save/compile the code and run my tests. This allows me to keep my focus on what I am trying to accomplish.

You can certainly run jasmine-node from inside Vim like with a simple command, but with mixed results:

The weird looking numbers are color codes sent to the terminal which the simple Vim terminal interprets in its own ways.

Turns out that jasmine-node, although it sports a --colors option, turns colors on for you even if you don't specify it. Fortunately there is a way to turn the colors off explicitly:

That's better!

The only thing left to do is to hook saving all files and running tests up  to a shortcut by adding the following to our .vimrc: (first line ensures our leader key is a comma)

 let mapleader=","
  map <leader>m :wa \|! jasmine-node spec --noColor <CR>

In this case hitting ,m will save all my open files and then run my tests.

Clean Test Output

In order to keep my test result output from being cluttered up with log messages and such, I replaces node's sys that is normally obtained via sys = require "sys", with a stub that does nothing when sys.puts is called.

Just to give an idea of how simple this is here is a quick example:

1. When creating the system under test, we inject the dependencies we want to stub - including sys

  @sut.init
    router: @router_stub
    sys: { puts: (msg) ->  } # stop sys.puts from cluttering up the test output
    process: process_stub

2. The system under test then uses the injected dependencies if present or the real ones otherwise

server.init = (fake = { }) ->

  sys = fake.sys or require "sys"
  router = fake.router or require("./lib/node-router")
  server = router.getServer()

  process = fake.process orglobal.process

More details will be explained in a later post.

About these ads

,

  1. #1 by Matt Freeman (@wtfcoder) on September 18, 2011 - 4:09 am

    Excellent blog post. WIll be brining the Coffee-Compile snippet into my environment. I always wondered what the garbage was, I think node-unit does same thing, i wonder if that has a noColor option

  1. How to make node.js, CoffeeScript and Jasmine play nice with Vim » Lab49 Blog
  2. Dependency Injection is dead, long live Verbs! « Thorsten Lorenz

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: