Refactoring: Unit-testing, TDD pains and myths
Soon we will be doing some major refactoring and looking at how to improve our code. I always feel bad that we don’t do everything to improve our unit-tests (test itself + frame and quantity of it). I have my own reservations and views on what unit-test framework should be, what should be “unit” and how it should be consumed. Granted that listening to Agile talk it makes you always feel bad, but then on doing some hunting (googling) around, I found quite a few detailed posts discussing myths involved with it.
I will summarize my take and point to all relevant posts as it is not useful to repeat content.
My views as bullet points:
- Unit-testing is useful and good to a certain degree. TDD is not the right way to develop any complex software.
- Most useful frameworks are simpler ones which provide ability to group and run tests, summarize results and requires minimal intrusion (provided as a single header or couple of files only). Any framework that needs to have lot of mock interfaces etc.. is useless.
- Value of unit-tests depends on the life of code. If interface is changing a lot then keeping updated test is a challenge. See how many unit-tests are broken in new code bases.
- System/Unit-tests are useful to test all major workflows, which would be hard to do manually.
- Testing a simple class for ctor/dtor, invalid state etc. adds very little value.
- I have not seen any large code (game engine, application etc.) which has incorporated TDD/unit-testing to all its glory!
- Rationalize your choice and decide to do what adds value.
Summary: I am NOT against writing unit-tests, but person writing tests has to define the concept of “unit”, understand its long term relevance w.r.t. code life, team and maintenance . Writing tests for major (or all) class does not provide much ROI. Also, you need some basic high level tests to tell you that all happy path and edge paths works!
How to handle next refactoring:
This will be exciting and interesting as each refactoring sort of needs good validation/testing framework. So that we have immediate feedback if something goes wrong. We need to think of each refactor task in terms of return or maintenance and prioritize it.
Further Reading:
- It’s OK Not to Write Unit Tests by Chris Ashton via MSDN – Very interesting and detailed post. MUST READ
- Testing Anti-Patterns: Overspecification by Jason Rudolph – how people write tests which do a lot more than test specific functionality. I think this tests end up being as system tests, so they are not so bad either.
- The "X Improves My Design Anyway" Myth by Sententia cdsmithus
- Your Unit Tests Lie to You by Janusz – Unit tests only verifies what we build into it, green does not mean everything is good and you can not test all setup paths.