Friday, January 25, 2008

ENOUGH WITH THE DAMN CODE COVERAGE ALREADY!

Whew!

Sorry about that, I just need to rant a little...

Here's what's got me so upset; TDD is a great cool thing. Everybody should be doing it. It's just the best thing since sliced bread, fluffy puppies and free Wi-Fi as Starbucks all rolled into one.

Now, I am NOT a TDD guru by any means. I've read some articles, tried rolling it into my approach and have had great results. I learn a little more everyday, and my understanding increases over time. If you really want to geek out on it you should talk to guys like Steve Harman and Jay Wren!

But there is an evil specter lurking that is threatening to ruin it all.

Code coverage.

Well, maybe not code coverage, but the way people with only a passing knowledge of TDD cling to code coverage like it's the last Red Bull in the fridge. The people who don't understand that the point of unit testing is not to increase code coverage at all cost, but to ensure your code does exactly what it is supposed to do; no more and no less.

I come not to bury code coverage, it's a perfect way to see what code is being tested, and more importantly what code is not being tested.

Here's where I get frustrated with peoples attitudes to code coverage (henceforth referred to at CC because I'm a lazy typist); there is a perception that a high CC number will guarantee quality code. That's simply not the case as you can hide a lot of skeletons behind a big enough door.

One "trick" I've seen to increase CC is to simply test EVERY method on the public interface of an object. This sucks.

My philosophy is that I really don't care about the individual gets/sets on a class. And to be honest, I don't like explicit tests of public methods on entities either. My belief is that you test the features. If you then find that there are methods and properties on a class that aren't being covered you have two options; either your tests suck or you don't need that property/method.

So maybe your tests suck. The best way around that is to make sure you write your tests first, THEN write your code. If you approach your tests like you approach your business requirements (user stories drive unit tests maybe?) and your test are meaningful this shouldn't be a problem, right?

Or maybe you don't need the property/method in question. I'm a big fan of pruning classes. If there is a method property on a class that never gets used why keep it? It sits there like a parasite, consuming maintenance costs and provides nothing in return. I say get rid of it!

We as developers/architects/information workers/whatever need to educate ourselves, our co-workers and are clients on this. High CC is NOT a panacea! The quality and intelligence of your tests is what ensures you are not developing crap-ware! Please, write your tests first, make sure all the features you develop are well tested. Review your co-workers tests and have them review yours. And if a high CC number is your goal look at what you are testing and don't be afraid to trim unused code!

OK, I feel better now. Code on!

6 comments:

Joe Wirtley said...

I definitely agree about code coverage not being the "silver bullet". Every time a new technique comes along there are some people who want to turn it into the "one true solution". Code coverage is a useful tool, but does not guarantee quality any more than TDD itself does (it's not hard to write crappy tests; I know from personal experience).

Software development is still difficult to do well, and no tool or metric is going to change that.

Brian H. Prince said...

Good post jb.

No one practice, tool, or philosophy will make you a great developer, or make you code smell better. It is the combination of the right tools and practices that will do that. And what tools and practices are 'right' vary by client, project, and goal.

Inexperience, (or recent scars to an experienced developer), will lead people to cling to one new thing that will solve all. Agile, tdd, ci, etc.

At the end of the day, it is not technology, process or anything else that guarantees success, but people and communication.

Only people, with experience and wisdon, that can step back and see what tools they have in their kit can/should be used on the job at hand can do what we do well.

Anonymous said...

Don't think of it as a 'door to hide behind', think of it as opening doors to look inside all of your closets.

Yes it seems meaningless to write a test for simple setters and getters, but just maybe it will force you to ask the question: why are we using them? I know that some styles just adopt them, but from an OO biggot point-of-view they are aweful and should be shot in the head. Tell me what to do, don't ask me for my data. OO 101.

The key to this though is that is forces you to look at every method you are developing, or have in the system (public, mind you). We so often have code in somewhere that is not needed, or doesn't belong. We as a development community have stopped looking at the code we write from the standpoint of the user using it (like writing an API without being the one who is going to use it). Getting to 100% code coverage makes you go through the steps of using the code in your system, and not just letting it sit there, fester and not be tested.

Also, think of Code Coverage as a safety net that you are bringing up. It takes time to bring it up to the height you want (do you want to fall 5 feet, or 40). But once you get it up as high as you want, they key is not dropping it back down. So part of the magic behing code coverage (sorry CC) is to make sure it _stays_ at the given percent.

Jon Kruger said...

So how do you really feel? :)

I agree with you. Our purpose is to write a piece of software... the unit tests are not the deliverable. The unit tests help to ensure that the software is reliable and does what it supposed to do.

When talking about 100% code coverage, I would question the value of unit testing certain aspects of an application. For example, in our Winforms app we are using the Model-View-Presenter pattern. We don't really test the presenters, because honestly, how much return are you getting on your time investment by testing something like a presenter? There probably isn't a whole lot of logic in the presenter, and in many cases you'll be testing a public method that is only used by one other class. It's unlikely that that method is ever going to break unless someone changes the actual method that's being tested.

James Bender said...

@Kruger - Yeah, I should have said something about that. I'm not a big fan of unit testing the UI either for a couple reasons.

For one thing there really should be any siginificant code there. It should just be what's needed for presentation and simple validation. My opinion is that complex validation should be abstracted out to a strategy that can be tested independant of the UI.

The other reason is that given my first point, the unit tests you write agains a UI are never going to be as meaningful as tests done by actual QA people who know the business.

James Bender said...

Oops! I ment to say...

For one thing there really should NOT be any siginificant code there.