Testability - a developers armour
Developers who love tests do better!

Testability - a developers armour

My third "...ility", and why software craftspeople concern themselves with the nonfunctional aspects of the code for your business and why it's so vital to your startup or scale-up. Much has been written on the subject of testing and why its so important. However, I still hear from many, many companies that still have code that does not have unit tests..... This article states why it can be so dangerous to your business, your engineering culture, the retaining of staff and your business being able to respond to change.

Imagine you are a developer starting a new job, with new colleagues in a new domain and a completely new code base. You meet your new product owner/CTO/CEO/team lead and they give you a detailed story to work on.. It's a story in an already large complex financial product with tens of thousands of live users and you are tasked with changing an obscure behaviour of the system. Its a moderately big story of say 6 weeks work(ish). You fire up your favourite IDE, you check out the repo and compile it and start looking for the unit tests to run to prove that all is working and you find.... you guessed it... none... zip... nada... bupkis... no tests whatsoever anywhere in the system... It's at this point the developer has a sinking feeling in their stomach and is likely to give a heartfelt sigh/groan/profuse swearing/question their life choices/hide under the desk.

They now have fear.

They as the last person to touch the code will be responsible for it. They are the ones that will get the call should this go wrong. They are the ones who will get shouted at when this breaks in production. This fear can be paralyzing. They now have to change complex code with no tests in place.... what does the lack of tests infer of the code base?

Several things: -

  • That the code will not have been written in such a way as to be testable;
  • There will be code that instantiates its own objects directly in its constructors (which in cascading fashion will also instantiate objects in its constructors);
  • It may refer to files on disk directly and therefore cannot be run without that file;
  • It may be tightly coupled with another class to such a point that one cannot be created without the other;
  • It may access a database directly;
  • It may call methods that require a huge amount of effort to mock so in effect there is likely to be little or no separation of concerns;
  • It may have secrets or keys hard coded as member variables;
  • It may even have hard coded third party API calls directly inline in a method.

Not being testable changes the way code gets written, developers are focused on the delivery of the functionality almost to the exclusion of anything else, thus short cuts are taken. The lack of tests also means that there is in effect no documentation of the system, no explanation of "Why does this class do this thing?", "What effect does this method have on domain objects?", "What state is the data expected to be in for this method to work?", "What is the state after?", "What is the effect of this method on the overall system or process flow?".

Instead of a 6 week story, your developer may now be thinking this is a 10 or 12 week story or even more, as they now have to go through every single class/method to discover why it is doing what it is doing... and as they touch things and change this for their own story they are then introducing more change in more places that will have unknown effects upon the system. If they are good they roll up their sleeves and start making the code they do testable.. but this is often the thin end of the wedge and the change snowballs... This makes deployment hard, and very high risk

When change occurs much code and user experience can (and usually does) then break, in fact in a large and distributed team and over time, this will occur more and more often, with greater and greater impact to the customers and business. This usually results in a large negative impact. So when a developer is trying to understand how something should behave as defined by the stakeholders in the business, how does a developer know when it’s right? The answer is an approach from the get go to define a series of tests, unit tests, integration tests, acceptance tests, regression tests, UI tests etc.… The key thing a software craftsperson will do is build this from the start integrated with their code and keep it close to if not at 100% coverage of the code base regardless of front end, back end, APIs or nature. This testing is armour for a developer, not only do they know if they have done what the stakeholder wants, when they later make a change elsewhere then the tests will fail BEFORE they check the code in, they will know what the impact of the change is. Thus driving the need to find and fix the issue either with the test OR the code that is broken. This produces higher quality code AND gives the ability for new developers to change the code without worrying about what will happen as the tests will capture and reveal the things that need to change. This value and driver of TDD or Test Driven Development will reduce or even eliminate the breaking changes problem, it also removes fear of change.

Secondly with the armour of comprehensive testing, this provides what I think is actually the most important aspect, it documents what a method does, what state the data should be in before it runs and what the change is after it runs. It helps with the understandability of a system. Given value X when calling method Y the result should be Z. This fits in directly with classic story architecture (as a X person I want to Y action so that Z happens) and enables a developer to know he has delivered functionality wise AND to document the system's code behaviour.

This drive for testability also does some really good things for your code base, you begin to see the need for dependency injection, the use of interfaces, the need for separation of concerns, the need to be able to isolate pieces of functionality and run them independently of anything else, the removing of hard-coded anything - if you cannot achieve this then the code isn't fully testable and you will have problems the moment you try to change anything - apart from the expected complaints from customers, the most severe impact from the companies perspective is that it will not be able to respond to change, or to deliver new features to the market as quickly as it should do-It becomes slow, painfully slow, existentially slow. This will mean your business, your startup, your scale-up will not be agile, is unlikely to succeed.

Internally with your engineering team culture if you do not address this issue you are likely to lose staff, have developers who are frustrated and annoyed that they cannot follow best practice.

Remember

Testing = Better code

Better Code = Being able to respond to change

Being able to respond to change = Better Business

Regards Julian


要查看或添加评论,请登录

Julian Guppy的更多文章

社区洞察

其他会员也浏览了