views:

120

answers:

2

I'm going to be doing a presentation on unit testing and in doing so I will touch on "design for testability" patterns. In other words using IOC containers, Dependency Injection, avoiding static methods etc.

I have a feeling my team will be cold to starting to code differently to accommodate for testing. So I was wondering if anybody knew of any real world examples of altering a design of something for no other reason then to make it easier to test.
I'm assuming this concept isn't uncommon in manufacturing, engineering and other professions, I'm just not familiar with any hard examples.

I imagine the development of the Saturn V rocket, Space Shuttle, Automobiles, Robotics, etc. must have some documented example of some design for testability or possibly the lack thereof causing problems.

Examples that have come to mind

  • I suppose having replaceable parts is a form of dependency injection, where as welding all the components together wouldn't allow testing them individually.
  • Perhaps the OBD2 port on modern automobiles because it makes it easy to check if any systems have issues.
+1  A: 

Many electrical surge protector have a Test button to check the correct functionality. It is a very clever form of testing, because it's not only in the hands of the developers, but also of the final users.

Another example: many control report lights (in particular in critical environments, like nuclear power plants and so on) have a button to turn them on and check if they are still functional. The same for many appliances using LED displays.

Batteries have a power indicator, so that you can test them before buying.

In sugar refinement, you monitor many steps of the production (sort of breakpoints) to assess the quality of the product. The plant is designed so to provide these testing breakpoints for easy accessibility by a human sampler (normally not well paid).

Finally, car makers include all sort of diagnostic. A car repair shop has a computer to perform full check on the status of the car. It's a sort of "after the fact" debug log, so not really "preventive testing", but still very useful and the inclusion of it is a real world "design for testability".

The main difference, however, between real-world testing and software world testing, is that real-world testing can ruin the product, to the limit of being destructive. For this reason, the faulty-to-good ratio is assessed via destructive sampling and analysis. In software testing, you never have destructive testing (unless you are a sadistic programmer with evil intentions)

Stefano Borini
A: 

If a set of components have been built so they can be tested, it is likely that they will be more modular and loosely coupled. For example it is easier to test code that uses an IOC container rather than a Service Locator as collaborators can be simply mocked and injected.

This separation follows into development. As the type has no hard dependency on its collaboraters, it allows composition of those parts in a different structure, which means it is simpler to refactor/respond to new requirements. You will also have more confidence in any refactoring as you have a suite of tests to verify your changes against.

Taken together this means in my experience that code written for testing is quicker and easier to modify, which results in less work for me, which I like.

Some real world examples of components designed for testing (themselves or other things) to avoid bigger problems down the line:

  • Smoke detectors
  • RCDs (residual current devices)
  • Pre-flight engine checks in aviation
  • Personal Breathalisers
Rich Seller