Skip to content

Testability

Quality Attribute · Chapter 4

Testability is how well a system supports testing in its context. Higher testability makes the system and its components easier to test; low testability often signals a flawed, needlessly complex design.

  • Testing is a significant share of development cost, so architecture that improves testability yields real savings.
  • Higher testability raises both efficiency (less time/effort to create and run tests) and effectiveness (more likely to find defects, and find them sooner).
  • Finding defects sooner keeps them out of production and makes them cheaper to fix — a large effect on overall quality.
  • Controllability — the ability to control the state of the system/component under test (SUT/CUT) by dictating its inputs and how far those inputs exercise it. Design for higher controllability.
  • Observability — the ability to observe the component’s state, including inputs and outputs, to confirm correctness. If the test framework can’t see inputs/outputs, results can’t be verified. Directly correlated with testability.
  • Isolability — the ability to isolate a component so tests (e.g. unit tests) focus on specific functionality without depending on other components. Enables testing a finished component before others are done and makes fault sources easier to pinpoint.
  • Automatability — the degree to which actions can be automated. Automated (pre-scripted) tests run any time — before check-in, before/within an automated build — giving fast feedback on newly introduced defects. See DevOps practices.
  • Complexity of the software — lower complexity means higher testability.
  • Structural complexity — the maintainability techniques (reduce LOC, increase cohesion, reduce coupling) also increase controllability and isolability, directly improving testability. See Maintainability.
  • Behavioral complexity — e.g. non-determinism: a non-deterministic algorithm can behave differently for the same inputs, making it hard to test. First identify non-deterministic areas; ideally refactor them to be deterministic or mockable.
    • Example: reading the current date/time tightly couples code to the host and is non-deterministic. Wrap that call in a class and inject it as a dependency so a test framework can mock it and specify the returned value.
    • Some cases can’t be made deterministic or mockable — e.g. a multi-threaded system interacting with an external component that raises events non-deterministically.

Tests should be runnable by testers who didn’t write them; good test documentation improves the reusability and maintainability of tests. Under agile, excessive documentation is treated as a risk — produce only what’s needed, and lean on self-documenting automated tests (clear method/class names, comments). Still, many test types beyond automated tests are involved and can be complex (business logic, inputs/outputs, setup data, broad scenario coverage), so some documentation pays off. It preserves tribal knowledge as testers rotate, leave, or are outsourced, and correlates with higher organizational maturity and project success.

Architects often guide testers. Strong testers are:

  • Efficient — organized and systematic, completing test cases and finding defects faster (not just stumbling on bugs).
  • Effective — focus on problems real users will care about in the released version, and document defects for developers.
  • Thorough — plan and document test cases; exercise all functionality; use varied inputs including edge cases (extreme/min/max values).
  • Knowledgeable of the software’s behavior — since not all inputs can be tested, understand what the software does and what could make it fail.
  • Aware of the whole environment — UI, kernel/OS interface, software interfaces (e.g. databases), and file-system interfaces.
  • Aware of the software’s capabilities — even a few basic capabilities (accept input, produce output, store data, compute) combine into complex functionality that must all be considered.
  • Software Architect’s Handbook (Packt, 2018), Ch.4 “Testability”, pp. 250-260.