Testing Strategies in Microservices Architecture
Microservices is an approach of developing an application by splitting it into smaller services, where each module run in its own process and communicating with each other in a lightweight mechanism. These services are independently deployed and fully automated.
Microservices is a new term introduced which changed the architecture of the software development, moreover, it changes the working culture of the teams the way teams work together.
What are Microservices?
Microservices architecture divides the complex application into smaller modules. This provides a number of benefits over the monolithic architecture.
Microservices architecture deploys independently increase of the other modules. Microservices take this approach to independent services. With microservices, we will easily be able to adopt technology more quickly and understand how new advancements may help us.
In short, the Microservices architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with light weight mechanisms, often an HTTP resource API.
These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
Image Source - ThoughtWorks
Multiple services work together to form whole application, Services like service A, service B and service C work independently, and they collaborate and form the whole application. These services collaborate for the functioning of the application. These chunks of services are called Microservices.
Benefits of Microservices
The benefits of microservices are many and varied. Many of these benefits can be laid at the door of any distributed system. Microservices, however, tend to achieve these benefits to a greater degree primarily due to how far they take the concepts behind distributed systems and service-oriented architecture.
The most important benefit of the microservices is that it deployed independently of the other modules. In case if there is need to make changes to the module other modules remain unaffected. If one module stopped working then the application as a whole will not be affected only that one module will be affected.
The application which was broken down into smaller modules will be developed parallel to different developer work on different module and development of all the modules is parallel.
Need of Testing in Microservices
It is very important to test the microservices as to be very confident about the assumptions made for each service that it will do what is says to do. Testing of microservices is the first step for making the service reliable for the user. For the internal functional dependency of the microservices, the testing is more important for the service to stay strong.
Challenges of Microservices
Microservices architecture includes numerous tiny independently services which integrate with each other to form the whole application. These microservices interact with each other in the production environment for the functionality of the application, although these small microservices are very simple while communicating with each other there arise many complexities. As the granularity of the application increases.
It is essential that a microservice application is built with an awareness of how it can be tested. Having good test coverage gives you more confidence in your code and results in a better continuous delivery pipeline.
As this is a new architectural approach so require a new approach of doing automated testing and quality assurance. New approach divides the specific layer of tests. There is five layer of tests that are performed over microservices -
Tests a single class or a set of closely coupled classes. These unit tests can either be run using the actual objects that the unit interacts with or by employing the use of test doubles or mocks.
In Unit testing, the smallest piece of testable software is tested in the application to determine whether it behaves as expected or not. Tests are typically run at the class level or around a small group of related classes. In unit testing, an important distinction is seen based on whether or not the unit under test is isolated from its collaborators.
Unit tests are usually written by the programmers using their regular tools - the only difference being the use of the same sort of unit testing framework.
There is further two types of testing in Unit Testing
Sociable Unit Testing
Solitary Unit Testing
Sociable Unit Testing - It focuses on testing the behaviour of modules by observing changes in their state. This treats the unit under test as a black box tested entirely through its interface.
Solitary Unit Testing - It looks at the interactions and collaborations between an object and its dependencies, which are replaced by test doubles.
Imagine you're testing an order class's price method. The price method needs to invoke some functions on the product and customer classes. If you like your unit tests to be solitary, you don't want to use the real product or customer classes here, because a fault in the customer class would cause the order class's tests to fail. Instead you use Test doubles for the collaborators.
Unit testing alone does not provide a guarantee about the behaviour of the system. Unit testing covers the core testing of the each module, however, there is no coverage of the test when these modules collaborate to work together to interact with the remote dependencies.
To be sure about each module work correctly with remote dependencies finer coarse-grained testing is required.
Integration tests are used to test the communication between services. These tests are designed to test basic success and error paths over a network boundary.
Different components interact with each other for their functional dependency, while communicating with each other integration test verifies the communication paths between the components and detect the interface defects.
Here, all test modules are integrated together and tested as a subsystem. It checks that the communication paths between the subsystem work correctly while interacting with its peers. In microservice architecture, they are typically used to verify interactions between layers of integration code and the external components to which they are integrating.
When the automated tests are written for the modules which are interacting with an external component, the basic goal is to verify the modules are interacting sufficiently with the external component.
It is very difficult to trigger the abnormal behaviour such as a timeout or slow responses from the external component. Special tests are written to ensure that test respond as expected in the unexpected circumstances
Persistence integration tests provide assurances that the schema assumed by the code matches that is available in the data store.
With unit testing and integration testing, we can have confidence in the correctness of the logic contained in the individual modules that make up the microservice, but we cannot be sure that the microservices work together as a whole to satisfy business requirements.
Tests the full function of a single microservice. During this type of testing, any calls to external services are mocked in some way.
A component is any well-encapsulated, coherent and independently replaceable part of a larger system. In a microservice architecture, the components are the services themselves.
A component’s complex behaviour is avoided by isolating it from its peers, also isolation help in controlling the test environment for the component.
Test the agreed contract for APIs and other resources that are provided by the microservice.
At the boundary of the external service, an Integrated contract test is done to verify the contract that is expected by the consuming service. This test verifies that the component meets a contract.
A test suite is written to verify only those aspects of the producing service that are in use. The behaviour of the service is not deeply tested, response latency and throughput should be within acceptable limits when input and output of the service call contain required attributes.
This test is written by each test consuming team and then packaged. The main aim of this test is to know the impact of the changes made by the maintainers on the consumers.
End-to-End Testing, Tests a complete flow through the application or microservice. Usually used to test a golden path or to verify that the application meets external requirements.
End-to-End testing tests the whole system from end to end. It verifies that the entire system meets the external requirements and eventually achieve its goal. Without bothering about the internal architecture of the application business goal should be achieved in the End to End testing.
The system is fully deployed and is treated as a black box and the test is exercised. With Public interference through GUIs and API, the system is manipulated. End to End Tests is more business facing.
This test verifies that the firewall, proxies and load balancers are correctly configured.
In microservice architecture, for one behaviour, there are many microservices which interact to respond to that behaviour, an end to end testing provides value by adding coverage of gaps between the system.
Different services pass messages to each other for a particular behaviour and this test ensure correct message passing between the services.
Microservices architecture is a distributed approach designed to overcome the limitations of traditional monolithic architectures. It helps to scale applications and organisations while improving cycle times, however, they also come with a couple of challenges that may cause additional architectural complexity and operational burden.
One of the benefits of microservice architectures is agility. Because each individual service has a focused scope and an independent lifecycle, it takes less time to implement a new feature as a microservice, test it, and deploy it into production.
Product NexaStack - Unified DevOps Platform Provides monitoring of Kubernetes, Docker, OpenStack infrastructure, Big Data Infrastructure and uses advanced machine learning techniques for Log Mining and Log Analytics.
Product ElixirData - Modern Data Integration Platform Enables enterprises and Different agencies for Log Analytics and Log Mining.
Product Akira.AI is an Automated & Knowledge Drive Artificial Intelligence Platform that enables you to automate the Infrastructure to train and deploy Deep Learning Models on Public Cloud as well as On-Premises.