Learning about coverage tools has been an interesting process. I liken writing tests without using coverage analysis to trying to optimise code without doing any profiling. With optimisation, it's easy to pick something that you think is a bottleneck and waste lots of time optimising it; in the same way, I've found that it's possible to write tests that you think are exercising the code in a satisfactory way, but actually aren't. Profiling helps to show exactly what's going on. In the course of analysing the library, I found a bug that should have been shown up in the tests, but wasn't, because the tests weren't exercising all of the code as I assumed they were.
Testing how code behaves in failure conditions is as important as testing how it behaves normally, so I wrote some code that uses #define macros to wrap the standard C allocation functions and allow the tests to simulate memory allocation failures. Again, coverage analysis is helpful here, too.
All in all, I'm not entirely sure why I'm writing a data structures and algorithms library, considering that all of these things have already been implemented hundreds of times over by different people. I originally wrote the library to remove the dependency of Irmo on GLib. Since then it's taken on a life and direction of its own, probably due to my own slightly obsessive nature. I think I just like the process of crafting something to the highest quality I possibly can.
(Also: Open source software with a test process? World coming to an end!)