Rather than get into a discussion on exactly how much design comes from TDD (for my money, TDD provides a checks-and-balances impact on my software designs, keeping me honest and minimal so it is useful for me) in this post I focus on the three forms of testing where there is most difference from other architectural styles.
1. Unit Testing still very much has its place
Some have claimed that unit testing has little impact with microservices, and it’s true that since the unit is often now the service itself the testing emphasis can switch a little to the service API itself.
Unit testing still has a very valuable role to play though. It’s still a powerful technical for enabling low-level comprehension, being the only place that the low-level original intent of the developer is actually, actively documented.
It is also often still the quickest set of tests to write and execute, particularly if you’re writing your services in Java, and so there’s still value in that too.
That said, the most valuable focus in microservices tends to be in ...
2. Implementation Agnostic Service API-level, Contract-First Testing is Crucial
In terms of providing a place to document your service’s intent, you can’t beat functional service API level testing.
Whatever your API is to your services, and our preference is often event-driven over resource/entity-centric (those options are often better used on Gateways), the intent of the service is best captured with an implementation agnostic, contract-first set of tests.
Tests are sometimes written at the raw level of the service API, but more often they are written using the client libraries that are provided for service consumers.
Those client libraries provide a small degree of control over the consumer from the service provide, as well as offering a simpler, language and platform sympathetic upgrade path for the service consumers.
3. Going Antifragile by Stressing Stressors
“If we don’t break it, our customers will” and so Antifragile Systems were born.
The term ‘stressor’ is common when discussing antifragile systems, such as I do in the Antifragile Software book, and the sorts of forces that such a system will not only embrace, but thrive upon.
Cause the stressor, then allow the system to improve to overcome it. Stressors are less of a traditional test as such, although stressors can certainly share a common heritage with stress testing.
Think “50 Shades of Microservices” and you might be almost there, tongue-in-cheek speaking. The idea is to actively create and apply the stresses that could occur and let those stresses guide and improve the design of the system.
This was the thinking behind the Chaos Monkey and its Simian Army, and applying the same approach to your own systems is a good idea when dealing with the massively distributed system that the microservices architectural style promotes.
The closer to the real production system you can create these stresses, the more power they will have and more positive impact on your system.
As soon as you apply this stressor/antifragile-thinking you begin to think quite differently about the management and monitoring of the systems itself.
Since stressors tend to focus on non-functional aspects they are often applied to a number of services integrated together. Failure is normal, even desirable, and so the last thing management and monitoring needs is a system continually bleating that it is experiencing failure when this is a good thing!
Instead of getting a system to bleat that it is ok, focus on what you want to actually know about the running system. At the same time causing problems so that the system design can thrive, compensate and improve base upon them.
Don’t wrap your system in layers of protective process and always-available resilience for all its pieces; instead cause failure and allow the system design to embrace and improve based upon it.