API/Microservices Testing

Published date: April 15, 2024, Version: 1.0

What is the objective?

The objective is to define a standard playbook that is desired to be followed for Microservices testing across different projects.

Microservices testing Overview 

What is Microservice ?

Microservices is an architectural style that structures an application as a collection of small autonomous, loosely coupled, collaborating services modelled around a business domain. These services communicate using language agnostic protocol, e.g., HTTP. The benefits of employing Microservices include creating more resilient, easily scalable and flexible systems that can be developed and deployed independently. 

How we test Microservice?

A combination of testing methods along with tools and frameworks that can provide support at every layer and how to go about testing at each stage is key to implementing an effective test strategy for Microservices architecture validation.

Approach

Microservice Testing Scope and Strategy

Below diagram depicts a high level view of different testing types in scope for any Microservice testing along with tools and technology that will be required right from the instigation phase i.e., sprint till the completion phase i.e., release to production.

Strategy

Types of Testing to validate Microservice

1. Unit Testing

  • The scope of unit testing is internal to the service. A Unit test exercises the smallest piece of testable software in the application to determine whether it behaves as expected. Tests are expected to be typically written at the class level or around a small group of related classes to confirm the functionality against the requirement.

2. Contract Testing

  • Contract testing is integral to microservice testing. These are tests at the boundary of an external service verifying that it meets the contract expected by a consuming service and are runnable at the build pipelines of the producing service. It mainly validates the availability of required attributes within the service input and output calls, response latency and throughput are within acceptable limits, communication protocols are correct etc.,
  • Developers will devise contract tests and configured within the delivery pipeline to identify integration issues much earlier before new service deployment happens.
  • Contract testing is of two different types as given below and the right method can be decided based on the end purpose the microservice would cater to and how the interfaces with the consumers would be defined:

3. Component Testing

  • Components are the services themselves that are well-encapsulated, coherent and independently replaceable parts of a larger system. Services are required to be tested in isolation with any dependencies being mocked or data generated randomly during run-time, thereby ensuring no calls are made out of the service. Mocking tool will be used for mocking test dependencies.

4. Integration Testing

  • The most critical part of microservice validation relies on the proper functioning of inter-service communications. Integration tests verify the communication paths and interactions between services under test and their various dependencies to detect interface defects. Service calls must be made with integration setup to internal/external services, datastores etc., and should include error and success cases to validate that the system is working together seamlessly and that the dependencies between the services are present as expected.

5. Performance Testing

  • In microservice architecture, multiple services are responding to each other to complete an E2E transaction. Early performance testing helps to verify whether each service response time is under network latency & with anticipated peak load. This can be achieved by introducing Performance tests early in the testing life cycle at the user story level against every microservice. However, the second level of performance validation should be executed in a production-equivalent environment to validate the conformance of services against all the Performance attributes, including CPU utilization. This execution should happen at the release level.

6. End-to-End Testing

  • Microservice architecture involves more moving parts for the same behavior. E2E tests help in identifying dependencies between services and helps in ensuring that data integrity is maintained between different services and other components. These tests verify that the entire system meets the external requirements and eventually achieve its goal. Also, it’s crucial to confirm that the overall system holds together without mocks/stubs to ensure there are no false assumptions baked into those mocks/stubs. It’s recommended to have the top layer of testing within a test pyramid be minimal since a failure is not expected at this point. The risk of failure and the cost of fixing the issue post integration is immense. Hence E2E tests should exercise certain ‘golden paths’ within the application.
end to end

Tools/Technology

  1. All the functional and Security testing can be performed with the help of UTAF

  2. Performance testing can be accomplished with the help of BlazeMeter

  3. Contract testing can be conducted with the help of PACT

  4. JUnit, POSTMAN, Swagger can be leveraged as Unit testing

Basic API test actions guideline

Each test is comprised of test actions. These are the individual actions a test needs to take per API test flow. For each API request, the test would need to take the following actions: 

  • Verify correct HTTP status code. For example, creating a resource should return 201 CREATED and unpermitted requests should return 403 FORBIDDEN, etc.

  • Verify response payload.

  • Check valid JSON body and correct field names, types, and values — including in error responses.

  • Verify response headers.

  • HTTP server headers have implications on both security and performance.

  • Verify correct application state.

API Test Flow

  • Testing requests in isolation – Executing a single API request and checking the response accordingly. Such basic tests are the minimal building blocks we should start with, and there’s no reason to continue testing if these tests fail.

  • Multi-step workflow with several requests – Testing a series of requests which are common user actions, since some requests can rely on other ones. For example, we execute a POST request that creates a resource and returns an auto-generated identifier in its response. We then use this identifier to check if this resource is present in the list of elements received by a GET request. Then we use a PATCH endpoint to update new data, and we again invoke a GET request to validate the new data. Finally, we DELETE that resource and use GET again to verify it no longer exists.

  • Combined API and web UI tests – This is mostly relevant to manual testing, where we want to ensure data integrity and consistency between the UI and API.