Building an E2E test suite in a distributed environment can be a challenging task, in many cases it could even be infeasible considering its complexity and cost, besides that, continuous integration pipelines execution could be very time consuming.
Instead of focusing on applications interactions and behaviors, developers probably would spend a considerable amount of time fixing environment specific issues.
One possible alternative to achieve the desired testing coverage in this scenario would be to use a CDC testing strategy (Consumer Driven Contract Testing).
Basically CDC testing is a process which consists of the consumer setting expectations about the provider, and after that, those expectations are validated at the provider side.
This kind of approach is well suited for scenarios at which the same organization is responsible for both consumers and providers involved in the solution.
Pact is a contract testing framework built on top of the CDC testing idea, it supports a reasonable number of programming languages, usually integrating with the Pact Broker or its commercial variant PactFlow. Pact Broker and Pact Flow provide an UI to visualize your system dependencies, pact verifications and other features.
Diving into the getting started docs, usually you will see examples of testing based on sharing of the contract file, being the consumer and provider located in the same repository. In this article we will see how we can tweak one of those samples to integrate with Pact Broker, in order to work with separated repositories and simulate a real world scenario.
To evaluate the Pact Broker in a development environment, you can use a docker compose file which suits best for your needs from this repo (docker-compose-dev.yml is a good choice for testing purposes). Once you have your pact broker instance running, you can go to the getting started docs of your preferred language. In this article we are going to use ruby.
The original tutorial is based on other web frameworks, but in that case we have created two rails api’s to evaluate pact features. One is the zoo app and the other is the animal app, being zoo the consumer and animal the provider.
We are not going to setup authentication features, since the server is for testing purposes only:
Zoo application Rakefile
require_relative "config/application" Rails.application.load_tasks requie 'pact_broker/client/tasks' PactBroker::Client::PublicationTask.new do | task | task.consumer_version = '1.0-beta' task.pact_broker_base_url = "http://localhost:9393" # assuming your pact broker instance is running on port 9393 end
After running our test suite from the consumer application (bundle exec rspec), the contract files will be generated (spec/pacts/zoo_app-animal_service.json/spec/pacts/zoo_consumer-animal_producer.json), and we can publish it to our Pact Broker using a rake task:
rake pact:publish
You will be able to see your pacts at the pact broker home page, and they are not verified yet, since testing from the provider is pending:
Our pact_helper at the provider side will look like that:
require 'pact/provider/rspec' Pact.provider_states_for "Zoo App" do provider_state "an alligator exists" do no_op end end Pact.service_provider "Animal Service" do app_version '2.0-beta' publish_verification_results true honours_pact_with 'Zoo App' do pact_uri 'http://localhost:9393/pacts/provider/Animal%20Service/consumer/Zoo%20App/latest.json' end end
There is a separated helper for testing messaging communication (message_helper.rb)
The “publish_verification_results true” snippet will enable publishing the test results to our pact broker. In order to use the pact contract published from the consumer, we configure the pact “Zoo App” to be loaded from the pact broker uri (pact_uri).
The Animal App Rakefile contains a task definition to verify messaging contracts and also is responsible for requiring Pact Tasks:
require 'pact/tasks' require_relative "config/application" Rails.application.load_tasks require 'pact_broker/client/tasks' Pact::VerificationTask.new(:messaging) do | task | task.uri 'http://localhost:9393/pacts/provider/Animal%20Producer/consumer/Zoo%20Consumer/latest.json', pact_helper: './spec/message_consumer/message_helper.rb' end
To run the tests related to our service at the provider side we can use the following rake task:
rake pact:verify RAILS_ENV=test
The article demo shows a very simple messaging test scenario, you can run it from the provider using the command rake verify:pact:messaging RAILS_ENV=test
After running both tasks from the provider, your pacts must be verified
.
Although contract testing is a great alternative to deliver quality in a distributed environment, there are some drawbacks, more specifically about using the Pact framework. Some languages provide better support and features than others, also sometimes it’s hard to find documentation or guides on using more advanced features. It is worth mentioning that having good communication between teams is essential to ensure your contract testing strategy will succeed.
There is a reason why there is a specific position in software engineering called Software Architect, and, if you ask 10 different people what software architecture is, you’ll have 10 different answers. On the other hand, if you ask 10 different people what an Architect is, most of them would say that they are responsible…
Feeling lost in your career? This can happen for a variety of reasons. Some feel lost because their work is not challenging enough, others feel stuck in their area and don’t know how to keep growing as professionals, and sometimes people just want a change. This is especially true in the software industry, where professionals…
It’s no secret that companies venturing on software development projects struggle with team productivity and even retention. Many get the unpleasant surprise of seeing their best expert leave when the project needs them the most. Why is it so difficult to achieve team stability, productivity, and satisfaction? It all comes down to talent experience. What…