I’ve been a professional web developer for fifteen years, and in that time I’ve had to learn a lot of new things. New languages, new techniques, and most of all, new mindsets. No new mindset has been as challenging to adapt to as that of test-driven development. This is my story of how I learned to stop worrying and love the test.

The task was simple enough; I was programming in the NodeJS environment and I wanted to create a recursive data structure representing a directory and all of its contents. In Node, almost all environment calls are asynchronous, so you tend to get a lot of nested callback functions, which ends up looking something like the following.

lib.method( param, function ( err, result1 ) {
  // throw error for other code to catch
  if (err) { throw err; }
	
  // do something with result
  lib.otherMethod( result1.foo, function ( err, result2 ) {
    // throw error for other code to catch
    if (err) {  throw err; }	
	
    // do something with result
    lib.yetAnotherMethod( result2, function ( err, result3 ) {
      .....
    } );
  } );
} );

Besides the general pyramidal hideousness of it, this code structure has another problem. When one of these asynchronous calls returns an array, each element of which you need to use for another asynchronous call, you begin to build bizarre data structures just to handle the state of all of the callbacks.

In an effort bring some sanity to the issue I began to convert some of NodeJS’s native fs methods with Bluebird’s Promisify capabilities. As I tested my first attempts on simple directory structures by printing out the resulting object to the console, everything looked fine. The console showed my directory as nested arrays, like this:

[ [ '/test/dir1/file1.txt', '/test/dir1/file2.txt'], [ '/test/dir2/file1.txt' ] ]

However, as soon as I tested my method against a more complicated directory, things started getting weird. Rather than the nice directory tree I was expecting, I saw an ominous-looking stump:

[ [ Object, Object, Object ], [ Object ] ]. 

If I went back to a simpler directory, it looked fine.

Now, some of you may have already figured out my problem, but I spent hours on this, convinced that I had messed up my .thens or .resolves somewhere in my Promise chain. After hours of fruitless refactoring, I finally wrote a little test (not in our unit test runner, by the way, but right in the source code) to check the types of each object in my structure. Shockingly, they were all correct! Suddenly, it dawned on me that the console was simply re-formatting my data structure once it got too deep - it had been working all along, and I didn’t even know it.

If only I had started out by writing a simple unit test of the functionality I expected, I would have been able to validate my first attempt (or my second, or third…). Instead I learned a bit about Promises, and quite a lot about the value of test-driven development.