{"id":14357,"date":"2019-12-23T18:25:36","date_gmt":"2019-12-23T12:55:36","guid":{"rendered":"https:\/\/coforge.site\/cigniti\/blog\/?p=14357"},"modified":"2023-10-04T08:59:52","modified_gmt":"2023-10-04T03:29:52","slug":"microservices-architecture-testing-strategies","status":"publish","type":"post","link":"https:\/\/coforge.site\/cigniti\/blog\/microservices-architecture-testing-strategies\/","title":{"rendered":"6 Best Microservice Testing Strategies to Follow in Different Architecture"},"content":{"rendered":"<p>Today, there\u00a0is\u00a0no dearth of\u00a0information\u00a0related to\u00a0microservices testing on the web\u00a0about\u00a0what\u00a0they\u00a0are and how organizations\u00a0are\u00a0transforming their development architecture.\u00a0However, very few articles\u00a0talk\u00a0about\u00a0the test strategies\u00a0that must\u00a0be followed while testing\u00a0microservice architectural solutions and applications.\u00a0This blog aims to help you provide the information.<\/p>\n<p>Before\u00a0I\u00a0continue to the Strategy, Test Areas, Test Types,\u00a0etc.,\u00a0let\u00a0us\u00a0understand some of the definitions of microservices.<\/p>\n<p>A microservice is a software development technique\u2014a variant of the <strong>service<\/strong>\u2013oriented\u202f<strong>architecture<\/strong>\u202f(SOA)\u202f<strong>architectural<\/strong>\u202fstyle that structures an application as a collection of loosely\u2013coupled\u202f<strong>services<\/strong>. In a\u202f<strong>microservices architecture<\/strong>,\u202f<strong>services\u00a0<\/strong>are fine-grained, and the protocols are lightweight.<\/p>\n<p>A microservice architecture builds software as a suite of collaborating services. Microservices are often integrated using REST over HTTP.\u00a0They\u00a0connect over networks\u00a0and make use of \u201cexternal\u201d data stores.<\/p>\n<p>Microservice architecture, or simply microservices, is a distinctive method of developing software systems that focuses on building single-function or single\u2013purpose modules with well-defined interfaces and operations.\u00a0This trend has grown popular recently as enterprises look to become more <a href=\"https:\/\/coforge.site\/cigniti\/blog\/7-best-practices-for-agile-test-driven-development\/\">Agile and move towards a DevOps and continuous testing\u00a0approach<\/a>. Microservices can help create scalable, testable software that can be delivered very often, as frequently as weekly and daily.<\/p>\n<p>Microservices architecture allows admins or users to load just the required services, improving deployment times, especially when packaged in containers.<\/p>\n<p>Microservices provide changes only when and where they\u00a0are needed. With a microservices architecture, the application monitors each functional component.<\/p>\n<h2>Why Do\u00a0You\u00a0Need a Special Strategy to Test Microservices?<\/h2>\n<p>It would help if you\u00a0had a different microservices testing strategy. They\u00a0follow a different architecture\u00a0and\u00a0have\u00a0many integrations with other microservices within one\u2019s organization\u00a0and\u00a0from\u00a0the\u00a0outside world (3rd\u00a0party integrations).\u00a0Additionally, these\u00a0require\u00a0much collaboration among different teams\/squads developing individual microservices. Moreover, they\u00a0are single-purpose services\u00a0and\u00a0are deployed independently and regularly.<\/p>\n<h3>The Microservices Testing Strategies<\/h3>\n<p>Before\u00a0discussing\u00a0the various\u00a0microservices testing strategies, let\u00a0us\u00a0look at a self-explanatory diagram to\u00a0understand the composition of microservices.\u00a0<span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><img decoding=\"async\" class=\" wp-image-14362 aligncenter\" src=\"https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/composition-1-555x197.png\" alt=\"\" width=\"732\" height=\"260\" srcset=\"https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/composition-1-555x197.png 555w, https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/composition-1-768x272.png 768w, https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/composition-1-833x295.png 833w, https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/composition-1-600x212.png 600w, https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/composition-1.png 1762w\" sizes=\"(max-width: 732px) 100vw, 732px\" \/><\/p>\n<p>Different types of <a href=\"https:\/\/coforge.site\/cigniti\/blog\/fintech-revolution-and-the-growing-need-for-performance-testing\/\">testing need to be performed<\/a> at different layers of microservices. Let us look at them using an illustration of three microservices collaborating\/working closely. Assume Microservices A, B, and C are <a href=\"https:\/\/coforge.site\/cigniti\/blog\/make-your-development-and-qa-teams-work-together\/\">working together<\/a> with many other Microservices (not shown in the picture). The following diagram illustrates all testing types and their boundaries by taking one microservice (Microservice B) as an example.<\/p>\n<h3>Unit Testing<\/h3>\n<p><em>A unit <a href=\"https:\/\/coforge.site\/cigniti\/blog\/5-reasons-go-independent-software-testing-service\/\">test exercises the smallest piece of testable software<\/a> in the application to determine whether it behaves as expected.<\/em><\/p>\n<p>Unit tests are typically written at the class level or around a small group of related classes. The smaller the unit under test,\u00a0the easier it is to express the behavior using a unit test.\u00a0With unit testing, you see an essential distinction based on whether or not the unit under test is isolated from its collaborators.<\/p>\n<p>In connection with the images above, unit tests are crafted explicitly for the internal modules within a given microservice, addressing each internal module individually. Techniques such as employing test doubles, stubs, and mocking are often utilized to substitute dependencies where necessary. Typically, unit tests are authored by your development team. In your capacity as a QA engineer, it is <a href=\"https:\/\/coforge.site\/cigniti\/blog\/why-is-automated-unit-testing-essential-in-agile-testing-projects-2\/\">essential to ensure that unit tests<\/a> are included as an integral part of their code commits.<\/p>\n<h3>Integration\u00a0Testing<\/h3>\n<p>Unit testing\u00a0alone does\u00a0not provide a guarantee\u00a0about the behavior of the system.\u00a0You\u00a0must address the coverage of the internal modules when they work together to form a complete\u00a0Microservice.\u00a0You\u00a0must also manage the interactions the modules make with remote dependencies.<\/p>\n<p><em>An <a href=\"https:\/\/coforge.site\/cigniti\/blog\/reducing-feedback-latency-using-continuous-integration-testing\/\">integration test<\/a> verifies the communication paths and interactions between the modules\u00a0and their dependencies.<\/em><\/p>\n<p>Integration tests collect modules and test them as a subsystem to verify that they collaborate as intended to achieve some larger behavior.\u00a0Examples of module integration tests demonstrate the communication between\u00a0Repositories and service Layer,\u00a0Service Layer\u00a0and resources,\u00a0etc.\u00a0Integration test\u00a0examples for external dependencies include\u00a0the tests between\u00a0data stores, caches,\u00a0and other microservices.<\/p>\n<p>You often write an extended version of your unit tests on the internal modules and start calling them Integration Tests. Thus,\u00a0it is a good idea to delegate the job of writing <a href=\"https:\/\/coforge.site\/cigniti\/blog\/integrating-automated-testing-into-devops\/\">automated integration tests<\/a> to your developers because it is easy for them to use the existing unit test frameworks to extend for Integration Tests. It needs them to use the actual instances of the internal modules involved (Ex: API Resources, Service Layer, DBs, and Message Queues,\u00a0etc.).\u00a0Testers can choose to do this activity provided the infrastructure team is ready to give you\u00a0an\u00a0integration environment with all the actual dependencies deployed.<\/p>\n<p>Write just a handful of test cases in both cases; do not automate an exhaustive list, as other testing types will cover the complete functional testing (Component Tests). These tests should act like a health check\u00a0activity\u00a0between the integration layers with a small test suite size.<\/p>\n<h2>Component Testing Microservices<\/h2>\n<p>With Unit and Integration Testing,\u00a0you\u00a0can gain confidence in the quality of the internal modules that make up the microservice. However, you\u00a0cannot guarantee that the microservice works together to satisfy the business requirements.\u00a0You\u00a0must end-to-end\u00a0test\u00a0the integrated microservice by isolating it from external\u00a0dependencies\u00a0and other collaborating microservices.<\/p>\n<p>A component test verifies the end-to-end functionality of\u00a0the\u00a0given microservice in isolation by replacing its dependencies with test doubles and mock services.<\/p>\n<p>In a microservice architecture, the components are the services themselves. By writing tests at this granularity, the contract of the API is <a href=\"https:\/\/coforge.site\/cigniti\/blog\/test-vs-behavior-driven-development\/\">driven through tests<\/a> from a consumer&#8217;s perspective. Isolation of the service is achieved by replacing external collaborators with <a href=\"https:\/\/coforge.site\/cigniti\/blog\/effective-practices-for-api-test-automation\/\">test doubles and using internal API<\/a> endpoints to probe or configure the service.<\/p>\n<p>The above microservice diagram shows that component tests focus\u00a0on\u00a0one microservice at a time. For example,\u00a0testing Microservice A in isolation,\u00a0and then B,\u00a0and then C,\u00a0and so on.\u00a0If Microservice A collaborates closely\u00a0with Microservice B and you want to test Microservice A in isolation,\u00a0then you would replace Microservice B with a mock service, integrate it with Microservice A,\u00a0and try it end-to-end.<\/p>\n<p>Testing such components in isolation provides many benefits:<\/p>\n<ul>\n<li>Limiting the scope to a single component makes it possible to thoroughly\u00a0perform an\u00a0acceptance test\u00a0for\u00a0the behaviour encapsulated by that component while maintaining tests\u00a0to\u00a0execute more quickly.<\/li>\n<li>Isolating the component from its peers using test doubles\/mocks avoids any complex behavior they may have. It also helps to provide a controlled testing environment for the component, triggering any applicable error cases in a repeatable manner.<\/li>\n<\/ul>\n<p>QA team is expected to define the coverage,\u00a0write\u00a0test scenarios,\u00a0and automate\u00a0them all.\u00a0You\u00a0can\u00a0use standard\u00a0API testing tools such\u00a0as\u00a0SoapUI, ReadyAPI,\u00a0REST-assured,\u00a0and HTTP\u00a0Client.\u00a0You\u00a0can see this as a typical <a href=\"https:\/\/coforge.site\/cigniti\/blog\/web-services-test-automation-framework-challenges-and-benefits\/\">web service testing<\/a>.\u00a0This involves extensive mock services to replace the\u00a0dependencies\u00a0to test microservices in isolation.\u00a0Wiremock, MockLab, MockableIO, and ServiceV are\u00a0a\u00a0few examples.<\/p>\n<h3>Contract Testing<\/h3>\n<p>With Unit,\u00a0Integration,\u00a0and Component Testing Microservices,\u00a0you can\u00a0achieve high coverage of\u00a0modules\u00a0that make up the microservice. However, the\u00a0quality\u00a0of the complete solution is not assured unless your tests cover all the microservices working together. Contract Testing of external\u00a0dependencies\u00a0and end-to-end testing of the whole system help\u00a0provide this.<\/p>\n<p><em>A contract Test is a test at the boundary of an external service verifying that it meets the contract expected by the consuming service.<\/em><\/p>\n<p>If two microservices or a microservice and its dependent services are collaborating,\u00a0then there forms a contract between them. Suppose Microservice A and B are collaborating where Service A interacts with Service B by sending\/seeking some data\u00a0and Service B\u00a0is\u00a0responding\u00a0to Service A for all its incoming requests. In that case, there forms a contract between Service A and B.\u00a0Here,\u00a0Service A\u00a0is known as the\u00a0consumer, and Service B as a provider.<\/p>\n<p>Contract testing takes place\u00a0in two steps:<\/p>\n<ul>\n<li>First,\u00a0the consumer will publish a contract for its provider. This contract looks like a typical API schema (can be a json file) with all the possible requests, response data and formats. This includes headers, body, status codes,\u00a0Uri, path,\u00a0verb,\u00a0etc. At the end of first step,\u00a0the contracts are published to the provider directly or to a central location.<\/li>\n<\/ul>\n<ul>\n<li>Second step is where the provider accesses the contracts given by its consumer(s) and verifies them against their latest code. If they find any failures,\u00a0then it could be due to some breaking changes the provider has made to their own API schema<\/li>\n<\/ul>\n<p>This way, the provider team can keep\u00a0all\u00a0their consumers (different groups within their organization or other clients\/customers) updated on the schema changes. This will help the consumer plan the change management well ahead.<\/p>\n<p>QA teams from both parties are expected to produce contract tests.\u00a0Contract testing also employs an interim mock service as\u00a0a\u00a0bridge between the consumer and provider\u00a0since\u00a0the testing takes two steps\u00a0in\u00a0different timelines.\u00a0PACT\u00a0is a great example of <a href=\"https:\/\/coforge.site\/cigniti\/blog\/challenges-in-implementing-test-automation-for-enterprise-applications\/\">implementing contract testing<\/a>.<\/p>\n<p>Contract tests are not functional tests. They are defined for the entire microservice and focus more on input\/output formats and types than actual values. Hence,\u00a0the suite size is expected to be smaller than the component test suites.<\/p>\n<h3>End-to-end Testing<\/h3>\n<p>The\u00a0system as a whole meets business goals irrespective of the component architecture in use. The whole system should be\u00a0treated\u00a0as a black box, and the tests must\u00a0be\u00a0exercised\u00a0as much\u00a0on\u00a0the fully deployed system as possible, manipulating it\u00a0through\u00a0public interfaces such as GUIs and service APIs.\u00a0Strictly, no concept\u00a0of mocking is observed here.<\/p>\n<p>As a microservice architecture includes more moving parts for the same behavior, end-to-end tests provide value by adding coverage of the gaps between the services.\u00a0You do not\u00a0have to write tests for each of the microservices\u00a0involved.\u00a0You\u00a0just need to find\u00a0a\u00a0few high\u2013level business workflows or user journeys (end-to-end journeys) and automate them.\u00a0Any UI and API\u00a0automation library\u00a0can be used. Selenium, in combination with REST-assured,\u00a0is a best example test framework.<\/p>\n<p><em>Writing and maintaining end-to-end tests can be very difficult, write as few end-to-end tests as possible.<\/em><\/p>\n<h3>Performance Testing<\/h3>\n<p>While the\u00a0importance of\u00a0<a href=\"https:\/\/www.cigniti.com\/services\/performance-testing\/\" target=\"_blank\" rel=\"noopener\">performance\u00a0testing<\/a>\u00a0is widely known,\u00a0it is worth mentioning at what level you perform this for microservices.\u00a0It is recommended that you do it\u00a0at two\u00a0levels:<\/p>\n<ul>\n<li>Microservice level (for each microservice when it is deployed)<\/li>\n<li>System level (when\u00a0all microservices\u00a0are\u00a0deployed to work together)<\/li>\n<\/ul>\n<p>It is better to have separate performance environments to do this. QA team can use any lightweight tool, such as JMeter and Locust, to measure the performance of each microservice. I recommend approaching specialized performance teams to do a detailed performance analysis of the entire system when all the microservices are deployed and integrated to work together.<\/p>\n<p><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><b><span data-contrast=\"auto\">Microservices\u00a0<\/span><\/b><b><span data-contrast=\"auto\">Test Pyramid<\/span><\/b><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><img decoding=\"async\" class=\" wp-image-14361 aligncenter\" src=\"https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/pyramid-1-533x300.png\" alt=\"\" width=\"590\" height=\"332\" srcset=\"https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/pyramid-1-533x300.png 533w, https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/pyramid-1-600x338.png 600w, https:\/\/coforge.site\/cigniti\/blog\/wp-content\/uploads\/pyramid-1.png 640w\" sizes=\"(max-width: 590px) 100vw, 590px\" \/><\/p>\n<p><strong>Unit Tests\u00a0<\/strong>are at the bottom\u00a0of the pyramid\u00a0with comparatively larger test suites\u00a0in size. They are written for each microservice and all of their internal modules\/components. The execution time is considered very\u00a0low,\u00a0but the scope of testing is higher with granular coverage.<\/p>\n<p><strong>Component Tests\u00a0<\/strong>are\u00a0second to Unit Tests in size as this is nothing but the full\u2013functional test suite for all microservices. You will cover the tests for all possible cases, boundary values, edge cases, positive and negative cases,\u00a0etc.<\/p>\n<p><strong>Contract Test\u00a0<\/strong>suites\u00a0have a\u00a0considerably good\u00a0size with a look and feel similar to component test suites,\u00a0but the coverage is limited just to the contracts, which means the input and output formats and types. You do\u00a0not have to test the functionality. Example tests for an API would be a test for 200 responses, another for 400 responses,\u00a0and one for 415 responses if applicable for each resource URI\/endpoint.<\/p>\n<p><strong>Integration Tests\u00a0<\/strong>are usually only a handful by, writing 2 or 3 tests for each integration among the internal modules and external APIs. The size is considerably small.<\/p>\n<p><strong>End-to-end Tests\u00a0<\/strong>are minimal\u2013sized suites\u00a0with\u00a0test scenarios concentrating on the major workflows and user journeys. The execution time is high as it may involve GUIs,\u00a0but the scope is limited.<\/p>\n<h2>Conclusion<\/h2>\n<p>With the understanding of what\u00a0<a href=\"https:\/\/coforge.site\/cigniti\/blog\/category\/microservices-testing\/\">microservices<\/a>\u00a0are, how to test them, what testing types to incorporate, and where to execute the tests w.r.t the environments, you are good to go with proposing the best test plan and microservices testing strategy that fits your organizational\/client needs. But this is subject to customizations and modifications based on many factors such as the cost involved in implementing all the testing types, resource capacity and availability, time and project delivery time scales, cost of test automation engineers, infrastructure, and hardware (e.g.: cloud), budget,\u00a0and many more.<\/p>\n<p>In\u00a0the next part of this\u00a0<a href=\"https:\/\/coforge.site\/cigniti\/blog\/\">blog<\/a>,\u00a0you will\u00a0understand when to run different test suites in the CI &amp; CD using the Quality Gates model.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, there\u00a0is\u00a0no dearth of\u00a0information\u00a0related to\u00a0microservices testing on the web\u00a0about\u00a0what\u00a0they\u00a0are and how organizations\u00a0are\u00a0transforming their development architecture.\u00a0However, very few articles\u00a0talk\u00a0about\u00a0the test strategies\u00a0that must\u00a0be followed while testing\u00a0microservice architectural solutions and applications.\u00a0This blog aims to help you provide the information. Before\u00a0I\u00a0continue to the Strategy, Test Areas, Test Types,\u00a0etc.,\u00a0let\u00a0us\u00a0understand some of the definitions of microservices. A microservice is a software [&hellip;]<\/p>\n","protected":false},"author":45,"featured_media":14358,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2337],"tags":[2065,2945,4184,2946,413,1242,2064,1243,2067,2066,2063,2947,2948,435],"ppma_author":[3737],"class_list":["post-14357","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microservices-testing","tag-automated-testing-of-microservices","tag-component-testing","tag-component-testing-microservices","tag-contract-testing","tag-integration-testing","tag-microservices-architecture","tag-microservices-test-automation","tag-microservices-testing","tag-microservices-testing-approach","tag-microservices-testing-framework","tag-microservices-testing-strategy","tag-performance-testing-of-microservices","tag-test-microservices","tag-unit-testing"],"authors":[{"term_id":3737,"user_id":45,"is_guest":0,"slug":"chandrakiran","display_name":"Chandra Kiran Mamidala","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/705ad8a6030f7832dfa9ec1d718b16b890152f8781356b3663202aeb9ac732ef?s=96&d=mm&r=g","author_category":"","user_url":"","last_name":"Mamidala","first_name":"Chandra Kiran","job_title":"","description":"Chandra Kiran Mamidala is an Associate Architect at Cigniti Technologies. He is part of the Delivery Team. He has an overall experience of 11+ years. He lives in Chester, United Kingdom\u00a0with his wife and kids.\u00a0Off work, Chandra is an enthusiastic badminton player."}],"_links":{"self":[{"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/posts\/14357","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/users\/45"}],"replies":[{"embeddable":true,"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/comments?post=14357"}],"version-history":[{"count":0,"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/posts\/14357\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/media\/14358"}],"wp:attachment":[{"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/media?parent=14357"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/categories?post=14357"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/tags?post=14357"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/coforge.site\/cigniti\/blog\/wp-json\/wp\/v2\/ppma_author?post=14357"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}