Guide to Writing Testable Code - Misko Hevery.
Our code is now fully testable. For the User class, we can easily mock the data source. (Testing the implementations of the datasource would be the job of a separate unit test). Our code is much more maintainable. We can switch out different data sources without having to change code throughout our application. We can create ANY data source.
A lot of C code is legacy code with few tests - and in those cases, it is generally easier to add integration tests that test large parts of the code first, rather than finely grained unit tests. This allows you to start refactoring the code underneath the integration test to a unit-testable state - though it may or may not be worth the investment, depending on your situation.
Having testable code (or for that matter unit tests) doesn't make the software smoother nor faster but it will help to specify an expected behaviour and allows a test to fail when the actual behaviour deviates from the expectation.
Why do people write unwieldy, untestable code? I see two reasons for this: Technical Debt: Most people don’t plan to write bad code. It just happens as more functionality is added over time. It’s often not feasible to refactor your code after a change, especially when your code is an API and your code rewrite could break your users code.
In essence the ideal interfaces are what separates the testable world from the legacy world. Once we have an ideal interface all we have to do is implement the adapter which bridges our ideal.
There are lots of best practices for writing testable code. The main goal for us is to create a robust solution that will be maintainable for everyone. Even if you don’t plan to write unit tests, you need to use this guide because it will help you to improve the quality of the code and the architecture in general.
These tests are written by developers, ideally at the same time as the product code. The key to good test automation is learning to write testable code. There are many benefits to following this development approach, such as better quality code in less time, reduced bug analysis and fix efforts, and being more responsive to changing requirements.