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:
  metric2: 5000 # this value will generate warning
steps:
    - echo: {from: '{{ RANDOM_INT }}', register: {metric1: '{{ OUTPUT }}'}}
    - echo: {from: '{{ RANDOM_STR }}', register: {device_id: '{{ OUTPUT }}'}}
    - 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
        query: 'select value from metrics where device_id == {{ device_id }}'
        register: {metrics: '{{ OUTPUT }}'}
    - run: metrics_check
    - postgres:  # check Saver put event in Postgres
        query:  'select count(*) from events where device_id = {{ device_id }} and value = {{ metric2 }}'
        register: {event: '{{ OUTPUT }}'}
    - 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.