NUnit 2.4 has been released. There is a lot in this one so if you use NUnit and have not upgraded to a point release for a while, you may want to look at this one. The item that leaps out at me is the change to the Assert syntax to use the idea of constraints, similar to NMock2.
I would always recommend using your xUnit tool in conjunction with a code coverage tool. Some folks view code coverage as just another piece of output on the cruise control box to ignore (shame on you!), but I would suggest being pro-active with code-coverage tools and actively running them with your xUnit tool and at very least before commiting your changes. Reviewing your code coverage it keeps you honest, because it will pick up code that is speculative and has no tests (or code where your test cases are not doing what you expect). If you are using NUnit, NCoverExplorer is a great tool, and is baked into TestDriven.NET. MSTest also includes integrated code coverage in VS 2005.
We aim for 100% code coverage. We do not hit it because of de-testable layers (for example in web applications anything that uses the ASP.NET runtime like HTTPRequest or HTTPContext) or because they violate Michael Feather’s rules on what it a unit test. The DB is a common one here, so we usually put code that talks to the DB (via an ORM or ADO.NET) behind a Repository so we can replace it with something in-memory for unit tests. We use a test double in those instances as to be able to unit test the remaining code. Some of those de-testable areas we can then pick up with integration tests, particularly around the DB, others you have to grab with tools like FIT, UI test tools (take a look at Selenium or Watir for free ones).
Interestingly my current team has few UIs and we have rolled our own test harnesses in WinForms for driving our application tests. Some of these work in a similar way to FIT – calling our application classes to do the end-to-end test – and we just found that the table driven idiom of FIT did not work well for us in that instance. In other cases it was easier to build a harness ourselves because we wanted to do something very different to what FIT offered. For example on our recent work server project one of the devs on the team built a test application that automatically submitted jobs to our store, over a specified time period. It allowed you to configure what records from a pre-populated db of test records to fill the store with. From there our work service would pick them up and the test harness also displayed the results of the work service loading those jobs. A big win of this homebrew test tool was that it enabled us to drive long-running tests of our work service.
Of course the irony is that the harness was not put together with TDD, a fact was often cursed when we needed to change it. So even those who preach can slip up in practice.