README
This getting started guide should help you get off the ground using Pact with Ruby. For more detail or advanced topics, head on over to the Ruby Pact GitHub repository.
Getting Started Guide
This workshop walks you through an example problem from start to finish, exploring most concepts that Pact supports. It takes approximately 2 hours to complete.
Installation
Add this line to your application's Gemfile:
And then execute:
Or install it yourself as:
Usage - an example scenario
We're going to write an integration, with Pact tests, between a Consumer
, the Zoo App, and its Provider
, the Animal Service. In the Consumer
project, we're going to need to need a model (the Alligator class) to represent the data returned from the Animal Service, and a client (the AnimalServiceClient
) which will be responsible for making the HTTP calls to the Animal Service.
Consumer
) project
In the Zoo App (1. Start with your model
Imagine a model class that looks something like this. The attributes for a Alligator live on a remote server, and will need to be retrieved by an HTTP call to the Animal Service.
2. Create a skeleton Animal Service client class
Imagine an Animal Service client class that looks something like this.
3. Configure the mock Animal Service
The following code will create a mock service on localhost:1234
which will respond to your application's queries over HTTP as if it were the real "Animal Service" app. It also creates a mock provider object which you will use to set up your expectations. The method name to access the mock service provider will be what ever name you give as the service argument - in this case animal_service
4. Write a failing spec for the Animal Service client
5. Run the specs
Running the AnimalServiceClient
spec will generate a pact file in the configured pact dir (spec/pacts
by default). Logs will be output to the configured log dir (log
by default) that can be useful when diagnosing problems.
Of course, the above specs will fail because the Animal Service client method is not implemented, so next, implement your provider client methods.
6. Implement the Animal Service client consumer methods
7. Run the specs again.
Green! You now have a pact file that can be used to verify your expectations of the Animal Service provider project.
Now, rinse and repeat for other likely status codes that may be returned. For example, consider how you want your client to respond to a:
404
(return null, or raise an error?)500
(specifying that the response body should contain an error message, and ensuring that your client logs that error message will make your life much easier when things go wrong)401/403
if there is authorisation.
Provider
) project
In the Animal Service (1. Create the skeleton API classes
Create your API class using the framework of your choice (the Pact authors have a preference for [Webmachine][webmachine] and [Roar][roar]) - leave the methods unimplemented, we're doing Test First Development, remember?
2. Tell your provider that it needs to honour the pact file you made earlier
Require pact/tasks
in your Rakefile.
Create a pact_helper.rb
in your service provider project. The recommended place is spec/service_consumers/pact_helper.rb
.
See Verifying Pacts and the configuration documentation for more information.
3. Run your failing specs
Congratulations! You now have a failing spec to develop against.
At this stage, you'll want to be able to run your specs one at a time while you implement each feature. At the bottom of the failed pact:verify
output you will see the commands to rerun each failed interaction individually. A command to run just one interaction will look like this:
4. Implement enough to make your first interaction spec pass
Rinse and repeat.
5. Keep going til you're green
Yay! Your Animal Service Provider
now honours the pact it has with your Zoo App Consumer
. You can now have confidence that your Consumer
and Provider
will play nicely together.
Using provider states
Each interaction in a pact is verified in isolation, with no context maintained from the previous interactions. So how do you test a request that requires data to already exist on the provider? Read about provider states here.