Saturday, March 26, 2016

On why we test (code)

I’m not a great programmer; I’m just a good programmer with great habits.

Kent Beck

Last week I had a talk with our lead software testing engineer, on multiple aspects of what quality in software development means. Even though it is just a cog in the grand scheme of quality assurance, maintainability of the code base strikes me  as one of those aspects for which the responsibility is entirely on developers.  Automatic tests, refactoring and diligence of the code reviewers are the only safeguards of the code quality. Other team members, testers and managers, will not be able to help us and some will through external pressure (deadlines and such) inadvertently contribute to its decay.  This brings us to the subject of…

Legacy code

Michael Feathers introduced a definition of legacy code as code without tests. When present and adequate, tests give us the confidence to make changes to the code without fear of regression (breaking something which worked). You can only fully appreciate this if  you maintained a code base  written by someone  else (quite possibly a group of people which is not available to you) over several years.  The key problem of legacy code is that it was never designed to be testable. So before writing our safety net of unit tests, we need to refactor the code to make it more testable. However, in order to refactor safely, we must have unit tests to verify that we haven’t broken anything while making changes…
Advice and techniques on how to deal with it, you can find in Michael’s book Working Effectively with Legacy Code.
I will be focusing more on how not to write legacy code.

Test first

This is a well known technique of the practitioners of the TDD.  The first step is writing a failing test. Yes, you write test before you write the production code. Why the f… would I do that?! – Because of the proper focus. Before you start coding, you can actually focus on the task your code needs to do. Getting invested with the technical details of the implementation may impair your vision of the place and purpose of the new code. Testing first will give you a perspective of how your code will be seen from outside and how it fits and collaborates with its surroundings. Writing the tests after usually means confirming that the code does what you wrote it to do. This is a valid goal itself.  However, we may be missing the insight we get while thinking about the problem from ‘client’ perspective. This insight could be integrated in the design and implementation of the solution. Other danger is that being invested in the solution, one might tend to compromise the quality and role of the tests, as being seen as something which just confirms something we already know (that our solution is good and it works).
One of my managers asked me once :
– How many bugs did you find with the unit tests?
None – unit tests are there to prevent bugs from ever entering the production code.

Testable code

Being able to produce good tests means that:
  1. You understand the problem you are trying to solve
  2. You have a good understanding of how your code needs to interact with other parts of the system
  3. You will produce a testable design
… So my design will be driven by tests…?
– To a point. From my experience, being able to produce the testable code most often dictates:
  1. You have removed tight coupling where it is inappropriate
  2. You have reduced the complexity enough be able to cover all relevant states and behaviors of your code to prove it is working as designed
  3. I will add stuff to this list as it comes to me
I’m not saying that you can’t achieve these goals without doing as I suggested. A very talented and diligent developer may produce good results without any tests whatsoever. However I find that such individuals are not as commonly found as we would like. And even if you are one, those around you might not be, and some of them will need to maintain the code you wrote. If you don’t take care about this you will make yourself indispensable. It means you are not likely to get fired as long as project lives. In other hand it also means you will  not work on that new cool project that came up.

No comments:

Post a Comment