Monday, January 23, 2023

Contract Testing - Pact


I have to set up contract-based testing in my team and I took a course from a test automation university which I am sharing via a blog post. 

Credits to : TAU, Rafaela Azevedo

Introduction

A contract test assures that services can communicate with one another and that a provider has fulfilled a contract that was anticipated by a service that is using it. Anywhere that two services can communicate with one another is where contract tests are applicable (an API with the front end, for example).

Contract tests may have a straightforward structure or a complicated one that involves numerous providers and consumers interacting. As is typical in a microservices design, the provider of one flow is frequently also the consumer of another.


Consumers and Providers

What do a provider and a consumer mean in this situation? Any party that offers a service for interactions with its dependents is a provider, and any party that uses an API to communicate with a dependent service is a consumer. A relationship between a consumer and a consumer can be seen in the interactions between various back-end APIs. Another example is the front end of a browser communicating with a back-end API.


Contracts

Consider a contract as a binding legal arrangement. A series of contacts with anticipated request and answer structures are represented by contracts.


Broker

Contracts are kept with a broker. Although any generic asset server will do, versioning support is preferred. Utilizing the open-source Pact broker, which is ideal for these specific requirements, is a viable solution. A bespoke factory broker can be created using Docker.



Contract hierarchy test

In the testing hierarchy, contract tests are located next to integration tests. There is a possibility to develop contract tests wherever the reliability of communications between services must be confirmed.


Integration tests versus contract tests

Contract tests have an advantage over integration tests in that they can be conducted without a full runtime environment. Tests can be done independently by interacting with mock consumers and providers to simulate real consumers and providers. Contract tests reveal issues with messages sent between services, whereas integration tests highlight issues with interactions between integrated units. This enhances system regression detection, warning programmers before errors are committed to providers or customers alike. Finally, contract testing enables users to create applications using API definitions before the provider API is formally finished.


End-to-end API tests versus contract tests

Functional testing from beginning to end will find inconsistencies that show up in output data or the user interface. Contract tests will only check that API endpoint connections are active and functioning correctly.

End-to-End tests, in contrast, take a lot of time to execute because they are rigorous and complicated in design. They frequently reveal important flaws that would otherwise go unnoticed. Although limited in scope, contract testing is less time-consuming and can be done more frequently to offer some level of smoke test coverage each time code is released.


Functional tests versus contract tests

Functional testing verifies that the anticipated system activity has taken place while contract testing concentrates on the messages that move back and forth between a customer and a supplier.


Using Pact to Mock Test Interfaces

Pact is a consumer-driven contract testing tool, which means that contracts are created while consumer tests are being run. The benefit of using this pattern is that it only allows testing of producer output that is really used. As a result, any provider behaviour that current customers do not use can change without affecting any testing.

You don't have to worry about Pact managing the mocking of provider and consumer objects or contract definitions. The test code is written using the test-driven development (TDD) methodology. Pact simulates a request being sent to a real server by producing a faked answer. It creates a JSON file called Pact.

The Pact JSON file is loaded when a test is triggered on the provider's end, and a verification procedure decides whether or not the contract corresponds to what a customer expects. In line with consumer expectations, Pact creates this contract file, which will be compared to what the actual provider server is actually transmitting.

Languages that Pact presently supports include:

  • Ruby
  • Javascript
  • .NET
  • JVM
  • Go
  • Python
  • Swift
  • PHP
To increase the overall quality of an application release, contract testing is most effective when performed in conjunction with other types of testing. Use Contract tests to find flaws in consumer processes, errors in end-point settings, or unexpected payload changes brought on by provider changes.