At our company we’ve had a few interns start this summer, so we ran a little workshop with the development team to help teach the team a few things about writing tests before writing other code. In our test driven workshop we did some simple problems in teams. We looked at different problems from Project Euler, and solved them in pairs. We all worked out our own tested solutions to the problems and brought them back to discuss. While looking at these we discussed what was good in each one and what could have been done better. We were pairing more experienced testers with the new guys for this exercise.
I think this went very well actually. These might not be production level challenges to work, but the variety of designs gives great insight into what people were thinking and how they were approaching the problem. I was delighted to see that there were small bits of code very similar between designs, but overall none of them really looked similar. Class names here and there might have been the same, but the implementations of classes with the same name could vary wildly.
After we finished with the exercise, we jumped back into teams to continue working. A while later I got into a discussion with one of our full-time developers and an intern where I ended up explaining one of the main reasons we like testing code. There is the obvious security of having the tests, but there is more than just that. One added bonus that not everyone seems to realize is that writing testable code creates some interesting properties in the code.
Why don’t we take a look at a few of the properties of testable code. I will certainly not cover all of them, but I will try to get enough to demonstrate my point. (these are in no intentional order)
A Few Properties of Testable Code
- Keeps dependencies to a minimum – Having fewer dependencies means less mocking, faking, and stubbing.
- Follows Single Responsibility – This keeps things as small pieces which makes for smaller easier to understand and maintain tests.
- Programming is done against interfaces – This allows you to mock and fake these objects, because your code only knows about the interface.
- Dependencies are injected into classes – Without doing this unit testing is impossible and only integration tests could be written.
- The code is well documented through the tests – The tests themselves describe how the code works, and this documentation stays up to date.
The neat part about this is the fact that these properties are present in maintainable code as well as testable. I'll sit here a moment while that sinks in..... Yes, you heard right that in order for code to be testable it must also be maintainable. If you ask someone how to write maintainable code, they might be able to spout off some information about theoretically how to do it. What is much harder is actually implementing solutions which are maintainable. This is why testing is important, because if you want to even be able to write the tests, the code first needs to be written in nice decoupled, well-organized ways.
I don't know about you, but I think it is very cool when you see that the properties of testable code seem to coincide with best practices for writing maintainable code.