I wanted to call this post "Softer Tips for Test Driven Development" but didn't want to exclude those who don't always 'test first'. So I thought about "Softer Tips for Writing Unit Tests" but there's sometimes confusion over what makes a unit
test. So I settled on the title above.
By "Smoke Test", I mean any kind of automated test where your code is tested with code. Maybe you use NUnit or maybe just a console application. They might be unit tests or integration tests that touch your database or filesystem. You get the idea.
I think everybody agrees that such tests are a good thing. Scratch that - they're an essential
thing. If you haven't seen the value in such testing yet then you aren't doing it properly. And if you aren't doing it at all I can't begin to tell you how you're missing out.
There are heaps of great bloggers out there with tips on the technicalities of writing such tests. If you're not familiar with Jeremy Miller
's work yet - then go and check out some of the great TDD posts in his archive. Roy Osherove
also posts the occasional stormer
such as his series on Achieving And Recognizing Testable Software Designs
However, I wanted to post some less-technical tips on writing tests.
Tip 1 - Don't worry about testing everything to begin with
If you've just inherited some code that has no tests or you've not been writing tests as you went along, then it can be daunting to think about creating a whole suite of tests. Don't let this put you off
You don't have to cover everything to start with. It's always better to run an incomplete set of tests than run none at all. The most important thing is to get started. When a bug does slip through, refer to Tip 2...
Tip 2 - Create a test that flags a bug before you fix it
If you or your QA team found a bug that wasn't showing up in your tests, the first thing you should do is add a test that flags it. Only then should you try and fix the bug.
Tip 3 - Try to write Unit Tests
A widely accepted definition of a unit test is a test which uses only a single module of code. The term 'module' is deliberately vague but it would usually be just a class, or at worst an assembly. It can be difficult to achieve (particularly when you're working with existing code) but it's the type of test you should aim to use.
Why? Well, if you're working on a large project with a reasonably sized team of developers you'll have a nightmare with any tests that span a number of modules. Inevitably, more than one developer will be working on an area touched by a single test which means your test will fail arbitrarily. Unreliable tests like this are seriously devalued - think 'the boy who cried wolf'.
Furthermore, if you can test your code with as many 'pure' Unit Tests as possible, you've almost certainly created a well factored object structure that will be easy to refactor and give you great agility.
It's widely held that a true Unit Test wouldn't touch the database or the filesystem (to read configuration, for example). Doing so would make it an Integration Test.. Roy Osherove gives a really good tip on how to remove the dependency on a configuration file using virtual methods in his post
I linked to above.
Tip 4 - Use a mixture of tests
Whilst Unit Tests should be the mainstay of your testing suite, it's nearly always a good idea to include some integration tests. Such tests are great for testing your data access layers (I tend to use transactions to keep the database tidy, more on this soon). Furthermore, I like to add a couple of end-to-end tests that hit the most recent CI build to make sure all the appropriate configuration is in place.