http://qs321.pair.com?node_id=487104

The short version of a longer story is that blakem loaned me his copy of Ian Langworth and chromatic's Perl Testing: A Developer's Notebook, and good things happened.

I've been reworking some old code TDD-style, commenting out the code, and only commenting lines back in when a unit test proved the need. Where the old code smells, I've been rewriting it, but only where there's test coverage. Thinking through testing has forced me to harden the code in some weak areas, and has flushed out a few problems that have been latent for the 5 years the code has been in production.

Though this approach has been working quite well, I've had nagging concerns about the quality of the tests. So I took authors' advice and hooked up Devel::Cover.

Wow. Nifty HTML charts with links to more nifty charts that point to code, branches, and conditions that the tests aren't exercising. I've used code coverage tools many years before, but never together with TDD. It's like discovering that my car has a pop-up GPS display.

The change to my development rhythm was immediate. "Write a test, watch it fail, then write the code to make the test pass; repeat" now includes periodically stopping to run the coverage tool to look for gaps in coverage, and to catch where untested code has crept in. It's a change in rhythm that I'm liking a lot.

One of the amusing things that coverage analysis showed up is that statement coverage in my existing tests was nearly 100%. The gap was in a few places where the tests needed to do different things depending on platform. Since pausing the tests to swap hardware is rather difficult, I'll have to accept life without a perfect score there, unless someone knows a trick. Coverage in non-test code was good on statements, but mediocre on branches, particularly when the branches involved error handling. Simulating errors in unit tests can be a nuisance, and I'd been avoiding it.

The book assumes that you're either working in either a ExtUtils::MakeMaker or a Module::Build world. I'm not, yet, so I had to tweak their examples around to get to something that would work in my old-school Makefile. Here's what I came up with:

test: prove t/*.t cover: cover -delete HARNESS_FOR_PERL_SWITCHES=-MDevel::Cover prove t/*.t cover
The cover target spits out HTML files.

Neat stuff. I recommend it. If monks have run into any Devel::Cover limitations, I'd love to hear about them.