Foundations of Test Architectures

Habitat 67 is a modular space in Montreal I recently stumbled upon Mike Cohn’s article Test Automation: Let Service Be Your Middle Man. It is abridged enough so not to need a summary. It made me realise that somehow the concept of system decomposition in software testing is not getting through as naturally as I had learnt it when I started thinking my first test architecture back in 2004. Mike explains it very clearly and I was happy to feel that there are more people sponsoring it as a key test strategy.

The motto is clear, test every piece of software as if it was a final product. In fact that is the reason you are encapsulating, decoupling, splitting responsibilities,… software design is a decomposition exercise. If you design your components for reusability, you should design your tests in sync. Besides, decomposition will help you achieving other practical goals:

1. Speed up testing: If you are the kind of tester that needs a full end-to-end production-like deployment before you can start testing, I am sure you are having lots of trouble shipping the product in time (and a lot of cranky peers). Component level acceptance tests allow for early testing of available pieces by parallel teams.

2. Test error scenarios: Intervening component interfaces is the only way to fake error scenarios (at a low cost). Yes, you can always wait for that API service to crash so you can test your HTTP 500 handling, query the database for a negative amount in a user bill, or wait for a user’s credit card to expire…

3. Automate the thing: Automation pays off, but the initial investment is high, and you will have to make trade-offs. Regrettably automating user interface tests is one of the most expensive tasks and you will often bear manual work (hopefully not forever, so you tracked that as test debt, didn’t you?). If the driver for all your tests is the user interface, you are moving at the slowest possible speed and that will kill your test execution performance. Take your chance to test-automate every inner part and defer manual testing to cover just the parts you couldn’t work ahead.

In my experience, this view is well aligned with micro-services architectures so don’t hesitate to put it into practice if that is your case. If that is not your context and you want to move towards it, the approach will help you getting there and won’t hurt you otherwise.