A respectable fellow recently asked me where I was on the Unit Testing spectrum: Skeptic <----> Zealot, or in between. Fair question.
I am right-leaning towards zealot though far from what I'd call a unit testing zealot. For one thing, I'm not into Test-first development. I've heard the arguments enough times but its not a mental barrier I care to break down. After years of struggling with laziness and mulling over the value of different approaches, this is a summary of my Unit Testing habits today:
- I use NUnit, TestDriven.Net, and NCover.
- I don't like unit testing strictly GUI aspects: Web Forms or Windows Forms, UserControl, etc. I know that there ARE ways to do this but it doesn't resonate with me right now. I somewhat dogmaticaly use Model-View-Presenter in ASP.Net and the desktop to minimize what is in the code behinds anyway. I use NUnit.Mocks to work with Mock instances of my View interfaces.
- I do a lot of up front design before I write anything non-trivial but I do not create models at the Implementation level. Writing the code is the first validation of my design, writing the unit tests is the second validation of my design. Sorry for bludgeoning the deceased equine but if I can't get at method to test it and it also doesn't make sense to test said method through some other calling method, then there's likely a smell in the design. I will typically revisit my preferred tool (currently StarUML) to see where the smell is, reimpliment, and take another stab at creating the appropriate tests.
- Unit tests are the most appropriate artifact you can leave behind for a project. It seems to me that I run across very few people who do what I would call Real modeling and fewer who make an effort to update models as a system evolves. I don't update models as a system evolves, but I do update unit tests. The tests are only valuable as an artifact if they pass and if they can be shown to actually exercise the system. See #5 regarding this.
- Code Coverage is the piece that finally made Unit Testing really click for me. Forming the habit of using NCover directly from Visual Studio via TestDriven is the single largest improvement to the quality of my code, ever. I find that I have difficulty inciting the same excitement about Coverage in other people, maybe because it forces one to admit they need to write more unit tests. So you've tested everything you thought of on the first iteration and NCover shows only 80% coverage of your business logic assembly. Sometimes you'll see you only tested the "Main success" flow through the code and you need to test the alternates and exceptions. Sometimes you will see NCover highlighting code that is absolutely never going to be called from your application. Many times I have caught "premature abstracting" using Ncover, classes or methods I assumed I'd need but nevered ended up needing. This may not be a defect but I'm of the opinion that if I ever need it I'll recover it from version control so I delete unused methods/properties/classes to make my assembly smaller and compile faster. Code Coverage is also a good aspect of a Code Review, if you're into those.
- I shoot for > 95% code coverage.
- While we work on stabalizing a release, testers sometimes find bugs! As I look at each bug, I think, could this have been caught before acceptance testing if there'd been a specific unit test? If I can think of a unit test for the bug situation, I add one.
- This one should be very obvious: I feel much better making huge changes to important code if there is a unit test suite.