Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Designing for Testability

EDIT:  What I should really say is that it isnt' just Designing for Testability, it's Designing with Testability 

From a question on my Passive View blog post

 "should we design for testability, or should we try and test what's designed (perhaps designed badly, so we refactor later)?"

Here's my take:

"Done, done, done" isn't just writing code.  It's writing code and verifying that that code works correctly.  You don't ship until the code is proven to work (hopefully).  Designing for testability might cost you extra time in coding (which I would actually dispute somewhat), but can easily save time in the whole by cutting down on the time spent debugging and testing.  I see testability design as a way to optimize the time to deliver, even if it ups the time spent on design or coding.

One of the very painful truths that TDD newbies learn the hard way (myself included) is that retrofitting automated tests to existing code can be very difficult.  Just trying to test what's designed may not work out very well, and frankly, I have yet to see a codebase that wasn't built with TDD that was easy to test.

What is Testability design anyway?  Granted, there are some things I do like opening up more public accessors or pulling out more interfaces strictly for testing that could arguably described as "bad."  However, most of what constitutes designing for testability, or using testability as a design heuristic, is a matter of how best to assign responsibilities by following older design principles that predate TDD by many years.  Achieving testability is mostly a matter of separation of concerns, coupling between classes and subsystems, and cohesion.  Exactly the design qualities that we've always strived for to make our code maintainable.  It's what we've been trying to do anyway.  If you practice traditionally good design, you might already be there to testability. 

Testability is, in my opinion, the ultimate design smell detector at the granular level.  If you're finding it hard to unit test your code, you've likely got a coupling or cohesion problem.  Testability is yet one more design tool to stick in your design toolbox right between UML/CRC modeling and code smells.  At least think of it this way, driving an application design at least partially through tests is yet another example of starting with the end in mind.  How will I know that this code works correctly?  How will I know that I'm done?

Yes, using TypeMock or switching to a dynamic typed language will let you more readily create testing seams with less conscious effort, but that's not the entire ballgame.  Throw testability and orthogonality out the window to write a ball of mud and no amount of TypeMock magic is going to help you out.

 

Anyway, go ahead and start arguing with me.  As always, comments are open.


Posted Fri, Jun 29 2007 8:30 AM by Jeremy D. Miller

[Advertisement]

Comments

Chuggle wrote re: Designing for Testability
on Fri, Jun 29 2007 10:50 AM

I agree completely with you - every since I started using TDD Ive found my designs have lower coupling and higher cohesion

Gotta love TypeMock....it should come with a warning though :)

Colin Kershaw wrote re: Designing for Testability
on Fri, Jun 29 2007 12:48 PM

"I have yet to see a codebase that wasn't built with TDD that was easy to test."

+1

My experience has been that mocking frameworks are often used to test "untestable" designs - treating symptoms rather than the cause (tightly coupled, loosely cohesive code).

Another great post - keep 'em coming.

Sam Gentile wrote New and Notable 176
on Fri, Jun 29 2007 1:15 PM

TGIF!! I am super busy right now designing a multi-CPU/multi-threaded Parallel Calculation Engine and

Gil Zilberfeld wrote re: Designing for Testability
on Fri, Jun 29 2007 2:30 PM

Right on!

I was actually discussing this with a colleague yesterday. She's starting with automated testing (not even TDD), and she's trying to put tests around the existing code.

It is hard. We need to unlearn the "produce code cause it's faster" for the things we learned in the university.

Sorry, but you won't get arguments from me.

ulu wrote re: Designing for Testability
on Sat, Jun 30 2007 5:40 PM

@Jeremy,

No, I won't argue with you. I completely agree.

Perhaps I didn't make myself clear. I didn't mean testing the existing code. By "testing what's designed" I meant "first design, diagrams and stuff, then write tests, then write code". I was thinking that we shouldn't design just for the sake of testability. But when testability is used as a criterion for a good design, yes, I'm all for it.

However, I'd rather treat testability as an advice, not as an absolute rule, and I don't like being forced by testability, even when it enforces something good ;)

Frankly, you got me converted to the view-presenter separation idea, I'm coding my first presenter now (or is it a supervising controller? i'm still learning these terms), and I feel much better about it. Still avoid these interfaces and dependency injections, my tools let me test everything without them, and I don't see any god they could make me in my case. Perhaps on the next project..

The Disco Blog » Blog Archive » The weekly bag– June 29 wrote The Disco Blog » Blog Archive » The weekly bag– June 29
on Sun, Jul 1 2007 9:23 PM

Pingback from  The Disco Blog  » Blog Archive   » The weekly bag– June 29

Designing for Testability « Tuff Stuff wrote Designing for Testability « Tuff Stuff
on Wed, Jul 4 2007 4:39 AM

Pingback from  Designing for Testability « Tuff Stuff

carnival of the agilists, 5-jul-07 « silk and spinach wrote carnival of the agilists, 5-jul-07 « silk and spinach
on Thu, Jul 5 2007 3:32 AM

Pingback from  carnival of the agilists, 5-jul-07 « silk and spinach

ulu wrote re: Designing for Testability
on Wed, Jul 11 2007 12:41 PM

Hi Jeremy,

I need an advice on TDD, and I thought I could ask my question here.

Suppose I want to implement a ComplexOperation method of my Controller class. Being converted to TDD recently, I break this into three smaller steps, and then write a test for it, mocking the calls corresponding to these steps. I end up with a test containing just 3 expectations and no asserts. Now, I write my ComplexOperation method with calls to these 3 steps, I've got a green, and I'm happy.

A couple of things look wrong here. First, my test doesn't help me to find mistakes with my code. If I forget a step, it will show both in my test and in my code. So, the test is not really testing anything. Second, if I choose to change my design, I'll have to change the test as well. There's no "refactor" step in the test-code-refactor trio.

The problem is that my test duplicates my code. It doesn't test the result, it tests the process. I don't see any way to include any assertions in this test, since it would involve implementation of my three steps. The question is, do I really need a test here? Or should I change my design?

Thanks a lot for your advice.

Jeremy D. Miller wrote re: Designing for Testability
on Wed, Jul 11 2007 10:08 PM

@ulu,

I'll try to shoot you an answer in the morning

Jeremy

Jeremy D. Miller -- The Shade Tree Developer wrote Best of the Shade Tree Developer Part II
on Thu, Oct 18 2007 9:20 AM

About a year ago I hit a patch where I wasn't able to blog much (something about finding a new job

http://146245.biztalk.codebetter.com/blogs/jeremy.miller/archive/2007/06/29/designing-for-testability.aspx wrote http://146245.biztalk.codebetter.com/blogs/jeremy.miller/archive/2007/06/29/designing-for-testability.aspx
on Wed, Apr 9 2008 11:53 AM
design for testability wrote design for testability
on Fri, Jul 4 2008 2:44 PM

Pingback from  design for testability

Sam Gentile's Blog wrote New and Notable 176
on Tue, Dec 2 2008 8:43 PM

TGIF!! I am super busy right now designing a multi-CPU/multi-threaded Parallel Calculation Engine and diving into the science of Parallel Computing. I'll have some links when I get a chance. Windows Workflow Tomas talks about Silver , the integration

Add a Comment

(required)  
(optional)
(required)  
Remember Me?