Thursday 14 May 2015

Whats The Unit of Smell?


As developers were very good at finding excuses to not test our code.
"Well that bit is difficult to test because......."
When we find ourselves saying things like this we should analyse why exactly is this code so hard to test?
Remember that ultimately unit tests are users of a class or an API, many things that make code difficult to test should have our noses twitching that there may be a smell with our design.
The perceived benefit of unit testing shouldn't be limited to just checking the code works, it should also be used as a validation that the code is well designed.
Good SOLID code in most cases is easily testable code, every violation of these principles will incrementally make the code more difficult to test. 
Single Responsibility Principle
Code that does more than one thing will be more difficult to test if only because of the overall number of test that will have to be written, if you find yourself writing a large number of tests many of which have no relation to each other maybe the class is doing too much.
Classes that break SRP will also often have a lot of dependencies, if the set-up of your tests is configuring a large number of mocks and your having to write a large number of asserts covering what happens with these mocks again maybe the class is doing too much.
Open / Closed Principle
Many a developer will bemoan the number of failing unit tests when they make a change to a class. While in one sense this proves the code is being well covered, a class that is constantly being modified, rather than extended, will soon gain a reputation as a developers re-factoring nightmare.
By breaking OCP your storing up a lot of trouble done the road where even minor changes becoming time consuming because of the constant attention that needs to be paid to the unit tests.
Liskov Substitution Principle
Classes in a large inheritance hierarchy can become difficult to test pretty quickly. There is no tighter coupling then between a sub-class and its super class and this time your mocking framework can't help.
If you find yourself having problems in unit tests separating the behaviour of your sub-class from its super class is this because the classes are ill bed fellows and shouldn't have been joined in the first?
As with most violations of LSP the mantra "Prefer composition over inheritance" will often save the day.
Interface Segregation Principle
Classes who have large and complicated dependencies will produce tests that can have multiple seemingly unrelated reasons to fail.
When violating ISP the amount of work done with mocks in unit tests will grow, several unrelated expectations will be set and the increased surface area of code the tests are exposed to will mean many a re-write when changes are made. 
Dependency Inversion Principle
Classes that can't be separated from there dependencies can become impossible to test, the coupling becomes so strong even the most determined developer can't separate them.
Classes that follow DIP are a joy to test, set-up your mocks and verify your expectations that's all there is to it. You'll achieve astronomical code coverage and be confident you know exactly what your code is doing and how its doing it.
So next time your trying to pluck up the courage to tackle the unit tests take a deep breath and smell the air, is that the whiff of a code smell?  

No comments:

Post a Comment