Archive for the ‘tdd’ Category

How to test your node.js app

Sunday, May 23rd, 2010

I’ve wanted to hack on a node.js project for a while, and a new app idea has given me the perfect excuse. My first question was: how do I test this? It’s a fairly new field out there, and there isn’t much help from node.js itself: it’s much more like Rack than a proper framework. So I spent some time coming up with one way to do it.

Disclaimer: I’m not that experienced with Javascript, particularly with the best way to define objects. I’d be grateful for patches to help improve the quality of the code here. I’ve also borrowed heavily from apprentice-us - thanks to Dave and Corey!

Overview

This is what I’ve got so far (the actual app I’m working will remain closed-source for the mo):

Example node.js github project

You probably want to refer to the code whilst reading the rest of this article.

To run the tests, run rake. To start the app, run node app.js (you will need to have node.js installed obviously).

If you install the watchr gem, and run watchr autotest.watchr, you’ll get robust autotest like functionality. I’m liking watchr much better than ZenTest right now.

How it works

The basic premise is to decouple the request/response handler from the server (see app.js, lib/http.js and lib/router.js). The interesting bit is in test/ integration/ user_sees_homepage.js - this then calls the dispatch method directly, passing in dummy Request and Response objects.

Note how I’ve defined the Response object. This allows me currently to write an integration test that looks like this:

router.dispatch(new Request("GET", "/"), new Response(function(headers, data) {
  assert.contains("200", headers['status'])
  assert.contains("Hello, world!", data)
}));

The assert.contains() method is not part of node.js: it’s implemented in test/helper.js.

The reason you need the asserts to be fired in the end() function is that node.js is inherently asynchronous and will finish executing this file whilst waiting for the haml file to load in lib/router.js. Try it yourself: if you put an assert at the bottom of the file it will fire immediately.

Unit tests

The plan is then to define whichever unit tests you need in test/ unit/ (something)_test.js, with the corresponding code in lib/ models/ (something).js. Just run javascript code in here and call methods on assert, and rake will execute it.

Improvements

You could potentially use the Sinatra-like framework Express to define lib/router.js - I’ve handrolled it for the moment. I’m of the opinion that you spot betterrefactorings by handrolling to start with: it could be that express.js isn’t right for my app, and I can’t easily tell yet.

There are a number of javascript testing libraries out there, but at the moment I’m happy with my own handrolled version, which just relies on the ‘assert’ package that node.js provides. There’s nothing to stop you using JSpec or some other javascript testing library: I wanted to keep things simple to start with.

I’m also aware that Cucumber now supports javascript through V8, which is an important step in the right direction. Unfortunately however it doesn’t yet support the commonjs package system, and doesn’t run through node.js but through raw V8. This makes it hard to use with anything but toy examples. Ideally I’ve love to plug Cucumber in in the future, if we can get it to use node.js as the platform somehow.

If you use it for something useful, let me know! I’d be very happy to receive patches and suggestions.

Why I think you should go to a code retreat

Wednesday, March 17th, 2010

17th March 2010

Last Saturday I went along to the UK leg of Corey Haines Code Retreat tour. Apart from the early start it was a really interesting day, and I really enjoyed the chance to pair with lots of new people.

The day was pretty tiring, pairing is always an intense experience, but I definitely learnt quite a lot. Its amazing how much fun working on the same problem several times in a row is, and how different approaches affect the way you think about it. By repeating the problem you allow your brain to concentrate on how you are solving it, rather than the problem itself. This gives you a really different perspective and is something I want to explore more.

There were so many things that I took away from the day, some of them are already changing my approach to building software:

45 minutes is a really short amount of time

The format of the code retreat is to work on the problem with a pair for 45 minutes. When the time is up, you delete all your code, and take break. Spend 15 minutes grabbing a coffee, reflecting on what you’ve done, and finding your next pair. Rinse and repeat.

Every 45 minute session flew by. Even so, with each pairing I was surprised at how far we’d managed to get. But what really surprised me, was how useful the short break and change of partner proved to be. The break gave you a real chance to reconsider your assumptions. That little bit of perspective was great in kick starting the next session.

It really surprised me how easy it was to swap pairs. Granted, everybody had been thinking about the same problem. But everyone was using a different approach, and sometimes a different language. The context switching didn’t seem to affect anybody. The new combinations brought new ideas and really contributed to the success of the day.

We’ve been trying the pomodoro technique at work. I know I’ve been a bit resistant to stopping when the timer goes. I always feel like I should just get the rest of my ideas out before I take break, but based on my experience at code retreat, I think the short break from the problem will turn out to be a real benefit. I’m determined to try and do it properly and see how it works out.

I also want to try and swap pairs more often. I think that the new perspective a new pair will bring to a problem will really help to come to the best solution. I’m not sure about every hour, but once or twice a day should be achievable.

Pairing is a great way to share insights and learning

Leading on from the new perspective a new pair brings is also the amount of shared learning that happens when your pairing. I learnt something from everyone I paired with. Not just how to approach the problem, but new things about the language, the tools. In a team, pairing will really help to bring every team member up to speed on any new part of the code base or library added. Switching often will make this happen even faster.

If you don’t need the infrastructure yet, don’t build it

Why do you need to build a class to make your first spec pass? Why not just write the code you need in the spec? Then write the next spec, and the code to pass it in that spec. As soon as you start to see shared behaviour extract a method. When specs are using the same state and the same methods extract a class.

Working like this is really hard, but its amazing how the design you need just starts to show itself.

Look at one behaviour at a time by isolating it using canned responses

Most of the code we write doesn’t split up nicely into discreet chunks of behaviour. We build systems that rely on several pieces all working together to produce complicated behaviour. Complexity is difficult to define, so to make it easier we need to try to isolate the part that we’re interested in right now. We can use simple objects that return canned responses, this allows us to consider only the behaviour we care about now.

Keeping things really simple is really hard

Corey was continually encouraging us to keep things simple. Its amazing how often you think your doing something as simply as possible, and then someone comes along and makes it even simpler. Simple is good, it allows you to work on one thing at a time, and not get bogged down in things that don’t matter right now.

A lot of the direction at code retreat was about ways to keep things simple, to specify only the smallest piece of behaviour. Writing the code in the spec at first, and using ‘doubles’ to isolate behaviour are both great techniques to help you do that.

One of the main things I’m taking away from code retreat is to work hard at writing smaller, more focussed specs.

If there’s a code retreat near you I really encourage you to go along. If there isn’t join the community and see if there’s anyone else who would be interested in helping get one organised.

I’d like to say thank you to Corey Haines, the sponsors RiveGlide and Eden Development, all of the attendees, and of course Bletchley Park and the The National Museum of Computing for making the day such a great success.

Presentation of my apprenticeship task

Sunday, February 21st, 2010

Here is a presentation i made to some of my colleagues on friday explaining my first apprenticeship task, my wiki, how i went about it, the problems i encountered and what i learnt from the whole experience.

See my Apprenticeship task presentation on youtube.

Licky wiki news

Thursday, February 4th, 2010

Just a quick update on licky, my little wiki apprenticeship task i’m doing. I realise that time has gone on and i haven’t talked about it as much as i might, plus i actually have some quite encouraging news to report now!

Last time i wrote, i was just starting to work on Pages and a PageFactory to find them or create them as necessary. Since then i’ve added a persistence strategy which saves wiki pages to the filesystem. I pass the desired directory to the strategy so that test pages can be kept separate from real pages. This was necessary as i wanted to clear out the test directory every time after use and i didn’t want to accidentally delete real pages.

After that little burst of progress i stalled for a long time as i knew i needed to start writing the web interface and i didn’t know where to begin. James gave me a good idea which was to set up a simple Webserver class that would wrap around the web server of my choice. I have chosen WEBrick for the time being, but it shouldn’t be too difficult to swap in another one later, probably with another strategy pattern. James suggested i start by visiting a page and looking for the text ‘Hello world’. I thought this was a good idea and so i started finding out about WEBrick servlets.

With that start i was suddenly able to leap ahead, testing and implementing everything i need so that my wiki is now able to create, show and edit pages through the web interface. I feel as if i am very close now. Possibly the only thing left to do is add a way to link between pages and then i can truly call it a wiki.

Test driving the development of this whole project has been extremely educational. I know i started off getting too involved in writing a test framework, so Enrique pulled me back and made me think of the simplest thing that could possibly work. I began with one method: assert_equal. That was enough in the beginning. As time went on i added two more methods: assert_true and assert_contains. When necessary i added useful debugging information to report failures. At the appropriate time i refactored the testing framework into a module that could be included into multiple test classes.

I know i also started thinking about the web server too early. I started off trying to work with ERB and templates, as i am familiar with Rails, and in the end all i needed was a few servlets. As Enrique made me realise, the most important part of a wiki is not that it runs on a web server. The most important thing is content. Pages, with content, saved to a file system. Having focussed on that and got a real solid, well tested mechanism for saving and retrieving pages, i knew that the WEBrick servlets could rely on the underlying framework, and when the time came, it did not let me down.

TDD ~ The Tortoise and the Hare

Thursday, February 16th, 2006

By the way...

This content is now pretty old: check the homepage for the latest.

Test Driven Development. Some people just don't get it.

Some people say: "A test for each feature? But that would mean writing twice as much code!"

These people usually go on to say: "It's just not worth it. I've finished my code, and it works, and you're still writing the test! I leave you in dust, you slow coding type!"

Then again, some people choose platforms, frameworks and even programming languages based on how easy it is to do TDD using them. If they can't do TDD ea sily, they pick something else. They're that committed to it.

The hare starts out faster. The tortoise is much slower out of the gate.

The tortoise knows that the finish line isn't when the code is written, it's when the customer has a working product. The hare might think they've finish ed, so they sit down and have a nap (or to stretch the analogy slightly, get bogged down fixing unnecessary bugs). That's when the tortoise overtakes.

I used to be a hare, running frantically back and forth over the whole codebase, changing things here and there until I thought I was done with a feature . Invariably I wasn't; there were bugs to be fixed and features missed. I thought just because I could write code quickly, I was adding value quickly.

And then I fell in love with TDD. Since I discovered it after reading "Extreme Programming explained" by Kent Beck (buy: uk us), I've not looked back. All o f my clients (like it or not), suddenly got test frameworks for free just so that I could develop using TDD. I rarely do any coding at all in any other way.

Why use TDD? Here are my main reasons:

Refactoring power. If I have a unit test testing each feature of my code module, I can merrily move stuff around internally as much as I like, without worrying if it's broken. At the end, I just run the tests. If it still works, I'm done.

Remembering what you are doing. It's very easy in a large application to get lost on which feature you are currently coding. If you are coding using TDD, then you can't get lost. There's a very simple cycle to follow: Write failing test. Write code so test passes. Refactor if necessary. If you forg et where you are, just run the tests. If they pass, you need to move to a new feature. If they fail, fix them. Simple.

Peace of mind. I've written a large application recently which bills customers weekly for products. When I release a new version of the applica tion, I have to know the billing is going to work. If it doesn't I get in a lot of trouble. Now I know the application is working before I release it , just by running "ant test" and waiting a couple of minutes.

Hares start out faster. But they get complacent, they have a nap, and invariably run into problems in the end. Tortoises get to the finish line first.

If you'd like to know more about TDD, visit these links:

A nice TDD essay, comparing TDD to MDD (model driven development).
A rebuttal of Microsoft's version of TDD, with a very good intro to 'real' TDD, by James Shore.