Doing TDD has become a way of life for me. One the one hand tests are the security net that lets me refactor my code, but is also a restricting force when it comes to changing code. Experience has showed that when I refactor, I also break a lot of tests that’s not relevant for the thing that has been changed. And the reason for this is usually set up of test data that has been scattered through my tests.
It’s not that setting up test data is that difficult, but unless you are structured and focus on not duplicating setup you will get into a mess. I found this interesting article at DZone describing a technique called Test Data Builders. Interesting idea I need to check out.
This is probably fairly well known, but I couldn’t find any doc on it when I searched so I’ll put it up here.
First off: Don’t load your Spring Context in your tests unless you absolutely have to. Some integration tests should load it, but keep it to a minimum. Loading the context is expensive, especially if you load up Hibernate and maybe H2 in that context.
Avoid loading the context is important both for speed and design. I have seen way too many tests where the context is loaded just because someone don’t want to do mocking. Besides, if you have to do a lot of mocking your design is usually too coupled, and should be changed.
So how can you speed up your tests in Maven?
Spring will cache the context and make sure it is only loaded once. But due to details I have not studied; in Maven, this only works for the tests that are in the same suite. It should work with fork=once on the surefire-plugin, but for some reason we need the suites too. Test which one works for you.
Drawbacks? If there is state in your context (database, stateful services) you will have created a dependency between your tests. That’s why, when it comes to database-testing you should use the AbstractTransactionalSpringContextTests which will automatically roll back your changes at the end of your tests. If state is modified in a way that has nothing to do with your database use setDirty() to signal to Spring that the context should be recreated for the next test. Of course then you get the time penalty of recreation.
Alright, so it’s a cheap one, but I had to do it. 😉 Alistair Cockburn coined the term GUTs – Good Unit Tests in a blog entry. Having a term for it was a bit of an eye opener.
I do TDD, but it’s not always the way I do stuff so I’m not religious about it. But wether I write the tests first or after, what I really strive to achieve is Good Unit Tests. TDD is a technique to make it easier to achieve GUTs, but it is no guarantee. What other techniques is there?
GUTs isn’t easy to achieve wether you write them before or after (thus I really have too many BUTs too), but that is what my system needs to be agile and avoid resisting change.