Tag Archive for 'test driven development'

why Test Driven Development (TDD) matters

Like many pro­gram­mers who first heard of con­cepts of Test Driven Devel­op­ment (TDD), I was like “What the heck? Yet more code to write for some­thing that won’t pro­duce end user output?”. I’ve been puz­zling for quite some time to get myself accept­ing this con­cept, because Code Com­plete men­tioned it so I thought it must have been a good thing (very great book by the way, every seri­ous pro­gram­mer should read it).

Code Complete by Steve McConnell

I some­times write unit tests and I think unit tests are very useful in some tricky areas. It’s just that I haven’t been moti­vated enough to try TDD (test first then write code).

Then today I real­ized how TDD is a nat­ural pro­gres­sion for people writ­ing unit tests. TDD pro­motes clean OO designs. In short, I can even almost say that “If you can test it, it has good design”.

I came across this real­iza­tion while trying to write unit tests for this piece of JavaScript code afterwards:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * Existing (bad design) JavaScript
 */


var Gateway =
{
ajaxGet: function(){},
};

// AccountManager uses Gateway, this is the “class” we want to test in this example
var AccountManager =
{
get: function ( id, onComplete )
{
Gateway.ajaxGet (/accounts/+ id , function ( profile ){ onComplete ( profile ); } );
}
}

That’s intu­itive enough, huh? As much as I thought it was, until I tried to write unit tests for it using JsMock, which has the typ­i­cal usage of:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * Typical JsMock usage example
*/


var mockControl = null;

function Worker(){}
Worker.prototype<span>  </span>=
{
doWork: function(){}
}

function setUp()
{
mockControl = new MockControl();
}

function testWorker()
{
var workerMock = mockControl.createMock ( Worker );
workerMock.expects().doWork();
workerMock.doWork();
workerMock.verify();
}

With the code I have writ­ten, it is impos­si­ble to do test­ing with JsUnit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * Attempt to test my existing code with JsMock (in JsUnit)
 */

var mockControl;

function setUp()
{
mockControl = new MockControl();
}

function testAccountManagerGet()
{
var accountManagerMock = mockControl.createMock ( Gateway );
<span style="color: red;">
// ERROR! mockControl.createMock() only accepts a class name,
// but Gateway is a variable name
</span>
}

So to make things com­pat­i­ble with JsUnit, I had to rewrote the whole stuff:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * My revised JavaScript compatible with JsUnit
 */
function Gateway (){}

Gateway.prototype =
{
ajaxGet: function(){}
}

function AccountManager ( gateway )
{
this.gateway = gateway;
}

AccountManager.prototype =
{
get: function ( id )
{
this.gateway.ajaxGet (/accounts/+ id );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * JsUnit tests for my revised code
 */
var mockControl = null;

function setUp()
{
mockControl = new MockControl();
}

function testAccountManagerGet()
{
// OK now, because Gateway is a class
var gatewayMock = mockControl.createMock ( Gateway );

var accountManager = new AccountManager ( gatewayMock );

// test fixtures
var id = “kizzx2”;

gatewayMock.expects().ajaxGet (/accounts/+ id );
accountManager.get ( id );

mockControl.verify();
}

The above changes might look redun­dant at first and not so intu­itive. But then I came to think of it, it removed the depen­dency between my Account­Man­ager class and the Gate­way class. I wasn’t quite aware of such anti-​pattern until JsUnit/JsMock brought it to my attention.

If I had used TDD in the first place, where I would have to write the tests first, it would have enforced me to use clean OO models to design things. Now I think that’s a pretty solid jus­ti­fi­ca­tion for using TDD.




Bad Behavior has blocked 32 access attempts in the last 7 days.