Design for Testability

Solutions should be designed - and code structured - in a way that makes execution of its tests happen more easily and quickly.

Rationale

Solutions that are designed with testing concerns in mind facilitate faster feedback and are ultimately able to release to customers and end users more frequently and safely. Designing for testability naturally leads to improved understandability and evolvability.

Implications

  • The internal state of a component or system should be understandable through deliberately-designed external interfaces or outputs, without invasive techniques such as attaching a debugger or filling the code with debug-level logging statements.
  • Structure your code to allow components to be executed in isolation in order to observe its behaviour during checking and testing.
  • Ensure that the components of a system are separated into well-defined responsibilities.
  • It should be easy to understand the components of a system - the code should be written in a way that is self-explaining and documented through its tests or, if necessary, through separate documentation.
  • Software should be designed and structured to support automation of tests wherever possible. These tests should run quickly and throughout the development cycle to support Continuous Delivery. Use exploratory testing as a supporting testing style for non-deterministic testing.
  • Carefully consider whether a diversity of technologies in use by a system introduces challenges in the testing methods and tools required, and adapt the approach accordingly.
  • Release frequently through to Production. This helps build confidence in testing and reduces risk in the release process, and any issues identified soon after the cause are easier to fix whilst still fresh in the engineer’s mind.

Further Reading