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 after­wards: /** * 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: /** * Typical JsMock usage example */

var mockControl = null;

function Worker(){} Worker.prototype = { 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: /** * Attempt to test my existing code with JsMock (in JsUnit) */

var mockControl;

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

function testAccountManagerGet() { var accountManagerMock = mockControl.createMock ( Gateway ); // ERROR! mockControl.createMock() only accepts a class name, // but Gateway is a variable name } So to make things com­pat­i­ble with JsUnit, I had to rewrote the whole stuff: /** * 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 ); } } /** * 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.

0 Responses to “why Test Driven Development (TDD) matters”


  • No Comments

Leave a Reply