If Your Code Is Hard To Test, It Probably Sucks
Recently, I had the displeasure of adding new functionality to some very old code.
Since I develop test-first, I immediately went to the unit tests for this code and started looking around. I planned on modifying the existing tests, adding new tests, and refactoring along the way. This way, I would ensure the new functionality was working properly, and did not have any negative effects on the existing code.
I soon discovered that a number of the classes did not have any tests. Annoyed and disappointed, I set out to get some tests around the areas I was going to be touching. I decided I would go back and add more tests for other parts of the code if I had time.
As I worked, I was amazed at how difficult it was to get tests around the code. Strange dependencies, improper abstractions, and duplicated code hampered my attempts to test. Eventually, I made the tests I needed and left the code a little better than when I got there.
This experience reminded me of an old adage:
Listen to your tests.
Your tests can tell you a lot about your code, and not just in the “this method returns the input multiplied by 2″ kind of way. By examining what you must do to create a test you can learn much about the code’s dependencies, abstractions, and interactions.
Do you have to make all sorts of funky objects to test something? Is it impossible to test something “straight on”? Do the assertions you make in one class’s tests look pretty much like the assertions in another class’s tests? Do your tests take a long time to run? If you answer yes to these questions, your code is probably hard to test.
All of which leads me to another old adage:
If your code is hard to test, it probably sucks.