C# Unit Testing – How to Ease Unit Testing Pains When Testing Alone

cunit testing

I have ran into this a few times where you get put on a project and you want to do unit testing of some type, but the project isn't setup right to allow for this and you might not have buy-in from everyone. The main issues tend to be code smells like issues with dependencies (especially the over use of statics) and seperation of concerns. New code that you write can be setup easily, but anything that operates with other legacy code or even those not drinking the cool aide can become an issue.

Some things that I have found are that isolation frameworks like TypeMock can make this easier. What are some other tools/tricks/best practices that you have found that ease this sort of pain?

Best Answer

Wow, this describes a recent situation of mine exactly on a large, existing project. No unit tests at all, and reluctance toward/skepticism of the idea. At the time of writing, I've been able to work with another person who favored it to get it more accepted (though he and I are largely the only ones that generally write tests). The code base was (still is) heavily laden with procedural static code, but it's getting better. Here are some of the things that I did to improve the situation:

  1. Immediately interface all singletons, especially ones in heavy use. Then, inject the interface into the new client classes you're writing to make them testable.
  2. Write wrappers for static classes that implement interfaces and inject those into new clients ala (1).
  3. Start gradually retrofitting your injected interfaces on former clients of static state/singletons and writing tests for them.
  4. Starting pulling functionality out of behemoth classes and testing the extracted, single-responsibility classes.
  5. Touched on earlier, but inject your dependencies!
  6. Write or factor to small methods and classes.
  7. Keep up the refactoring until you can finally kill the singletons/statics.

These are ways to make your code more testable (and, I would argue, better in general), but selling the process to others is a different matter. I would offer the following advice for that:

  1. Write tests and show people how to do it (the biggest barrier being a literal lack of knowledge of how to write tests).
  2. If you review people's code, write a unit test to expose a problem instead of telling them about it. Show them the failing test and task them with making it pass.
  3. Make sure your test runs execute quickly - long running test suites will rot and annoy people.
  4. If the application is large, show people that the feedback loop is much faster for modify-test-refactor than it is for modify-build-run-maniulate-gui-observe-refactor.
  5. Unit test a feature that you write and keep objective statistics (defects reported per LOC) to compare to non-tested code. This is a win with management.
  6. Along those same lines, run static analysis/metrics on the unit tested code which, in my experience, tends to score better than non-tested code. Objective metrics are hard to argue with.
  7. Point out to people that guarding their code with unit tests makes it harder for someone to come along and mess with their code in defiance of their original intentions. Sounds petty, but this is often a selling point for people when they realize it.
  8. Product implementation documents or writeups for consumption by stakeholders that emphasize code coverage or number of tests. This creates the (accurate) impression that your code is demonstrably reliable and managers/analysts/PM types might start asking others where their coverage/test metrics are.
  9. Finally, and this is the one that I've found to be most eye opening or other developers, demonstrate the power of unit testing (specifically TDD for this one). Pull off a coup like a major refactoring of your work in less than a day or having your code execute perfectly the first time you put it all together and run the application. Developers who code it up and then spend a few days in the debugger programming by coincidence will be sobered by this in a way that they won't be all the unit test proselytizing in the world.