One of the most common misunderstandings for developers new to unit testing is the value of code coverage. We intuitively know that if coverage is low, we don't have enough tests, and if coverage is high, we probably do. Some IT shops even set minimum code coverage percentages, so if you check in code that drops the coverage metric below 80%, you fail the build.

One way to get higher code coverage is to generate the tests. Visual Studio has versions that can do this for you. Point the code at a class, click OK a few times, and all your code in the class under test can be covered. In fact, the generated test usually check for things you might not bother to, like what if there is a negative value passed in to a method, what if a zero passed in, what about a null, etc. How can this be bad? We're exercising the API of our class more fully, right?

What not to test

I think the focus needs to be on testing the right code in the right way. There is no point in testing the .NET framework. If you have a auto property that is an int, you don't need to test -1, 0, 1, and null. If int stops working, everyone using .NET has a bug. But int isn't going to fail, and even if it does, it's not your code anyway (unless you work at Microsoft on the .NET framework team).

So the first rule is be sure you're testing your code. That means testing your methods that do real stuff. If you have a method in your class that just wraps a call to another class, there really isn't anything worth testing. All you can test is that the class can be created and the method can be accessed and has those parameters and they are of that type. But you can do that better by testing the underlying class instead of the pass-through method.

Go faster when refactoring

In fact, testing these properties and pass-through methods and no arg constructors increases your code coverage numbers without adding anything meaningful to the test suite. The net negative comes into play when it's time to refactor, whether it's adding or removing properties, renaming, moving things to different classes, etc. Generated tests can really slow you down here as the new code stops building and the generated tests have to be removed and regenerated.

A better way is to write the tests you need first, then add the code to implement that business rule or feature. Whether you're using TDD, BDD or something else, you'll end up with tests that express the intent of the code rather than its implementation. Tests should emphasize the features of the application, not the coding artifacts. These are the kind of tests that add real value to your project.