Testing microservices ===================== Imagine you have a Metrics for IOT, with microservice architecture:: Metrics And Events Metrics ---> Receiver ---> Kafka --------> Saver ------> Postres || /\ || Metrics || || || Metrics || || Events || and Events \/ || \/ Processor <-------> Redis Assessor -------------> Events Warning -------------> Sensor Statistics counters | `Metrics` service collect metrics from devices and sends to the `Receiver`. | `Receiver` aggregates metrics and sends them to `Kafka`. | `Processor` reads metrics from `Kafka`, process them and puts generated events back to `Kafka`. It also uses `Redis` for warning counters storage. | `Saver` microservice saves all metrics and generated events to `Postgres`. | Finally `Assessor` takes events and statistics from `Postgres` and renders it to user or external services. How to test? ------------ | Each input request pass through the 9 services. Error can be in any of them. And full coverage of one service with unit or functional tests won't help you, because bug can be everywhere. In deploy configuration, wrong protocol in microservices communication, etc... Catcher will help you:: --- include: - file: metrics_check.yaml as: metrics_check variables: metric1: '{{ RANDOM_INT }}' device_id: '{{ RANDOM_STR }}' metric2: 5000 # this value will generate warning steps: - http: # send data to the Metrics service actions: - post: url: '{{ metrics_url }}/metric' body: {device_id: '{{ device_id }}', value: '{{ metric1 }}'} - post: url: '{{ metrics_url }}/metric' body: {device_id: '{{ device_id }}', value: '{{ metric2 }}'} - kafka: # check Receiver put aggregate metric in kafka consume: server: '{{ kafka }}' topic: 'metrics' where: equals: {the: '{{ MESSAGE.device_id }}', is: '{{ device_id }}'} register: {value: '{{ OUTPUT.value }}'} - check: # check metric's value was properly aggregated equals: {the: '{{ value }}', is: '{{ metric1 + metric2 }}'} - wait: {seconds: 0.5} - kafka: # check event for metric2 was generated consume: server: '{{ kafka }}' topic: 'events' where: and: - equals: {the: '{{ MESSAGE.device_id }}', is: '{{ device_id }}'} - equals: {the: '{{ MESSAGE.value }}', is: '{{ metric2 }}'} - postgres: # check Saver put 2 metrics in Postgres sql: 'select value from metrics where device_id == {{ device_id }}' register: {metrics: '{{ OUTPUT.value }}'} - run: metrics_check - postgres: # check Saver put event in Postgres sql: 'select count(*) from events where device_id = {{ device_id }} and value = {{ metric2 }}' register: {event: '{{ OUTPUT.count }}'} - check: '{{ event == 1 }}' - http: # request statistics from Assessor actions: - get: url: '{{ assessor_url }}/statistics?device_id={{ device_id }}' register: {measurements: '{{ OUTPUT.measurements }}'} - get: url: '{{ assessor_url }}/events?device_id={{ device_id }}' register: {events: '{{ OUTPUT.events }}'} - run: # check proper statistics include: metrics_check variables: {metrics: '{{ measurements }}'} - check: contains: {the: '{{ metric2 }}', in: '{{ events }}'} `metrics_check.yaml`:: --- steps: - check: and: - equals: '{{ metrics|length == 2 }}' - contains: {the: '{{ metric1 }}', in: '{{ metrics }}'} - contains: {the: '{{ metric2 }}', in: '{{ metrics }}'} With this Catcher test scenario you can always be sure, that every component of your system is working properly.