README.md in pacto-0.2.5 vs README.md in pacto-0.3.0.pre

- old
+ new

@@ -1,5 +1,10 @@ +[![Build Status](https://travis-ci.org/thoughtworks/pacto.png)](https://travis-ci.org/thoughtworks/pacto) +[![Code Climate](https://codeclimate.com/github/thoughtworks/pacto.png)](https://codeclimate.com/github/thoughtworks/pacto) +[![Dependency Status](https://gemnasium.com/thoughtworks/pacto.png)](https://gemnasium.com/thoughtworks/pacto) +[![Coverage Status](https://coveralls.io/repos/thoughtworks/pacto/badge.png)](https://coveralls.io/r/thoughtworks/pacto) + # Pacto Pacto is a Ruby implementation of the [Consumer-Driven Contracts](http://martinfowler.com/articles/consumerDrivenContracts.html) pattern for evolving services. Its main features are: @@ -30,96 +35,121 @@ - Body: a JSON Schema defining the expected structure of the HTTP response body. Pacto relies on a simple, JSON based language for defining contracts. Below is an example contract for a GET request to the /hello_world endpoint of a provider: - { - "request": { - "method": "GET", - "path": "/hello_world", - "headers": { - "Accept": "application/json" - }, - "params": {} - }, +```json +{ + "request": { + "method": "GET", + "path": "/hello_world", + "headers": { + "Accept": "application/json" + }, + "params": {} + }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json" - }, - "body": { - "description": "A simple response", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "body": { + "description": "A simple response", + "type": "object", + "properties": { + "message": { + "type": "string" } } } + } +} +``` The host address is intentionally left out of the request specification so that we can validate a contract against any provider. It also reinforces the fact that a contract defines the expectation of a consumer, and not the implementation of any specific provider. ## Validating Contracts There are two ways to validate a contract against a provider: through a Rake task or programatically. ### Rake Task -Pacto includes a default Rake task. To use it, include it in your Rakefile: +Pacto includes two Rake tasks. In order to use them, include this in your Rakefile: - require 'pacto/rake_task' +```ruby +require 'pacto/rake_task' +``` -Validating a contract against a provider is as simple as running: +Pacto can validate the contract files: - $ rake pacto:validate[host,dir] # Validates all contracts in a given directory against a given host +```sh +$ rake pacto:meta_validate[dir] # Validates a directory of contract definitions +``` +Or it can validate contracts against a provider: + +```sh +$ rake pacto:validate[host,dir] # Validates all contracts in a given directory against a given host +``` + It is recommended that you also include [colorize](https://github.com/fazibear/colorize) to get prettier, colorful output. ### Programatically The easiest way to load a contract from a file and validate it against a host is by using the builder interface: - require 'pacto' +```ruby +require 'pacto' - WebMock.allow_net_connect! - contract = Pacto.build_from_file('/path/to/contract.json', 'http://dummyprovider.com') - contract.validate +WebMock.allow_net_connect! +contract = Pacto.build_from_file('/path/to/contract.json', 'http://dummyprovider.com') +contract.validate +``` +If you don't want to depend on Pacto to do the request you can also validate a response from a real request: + +```ruby +require 'pacto' + +WebMock.allow_net_connect! +contract = Pacto.build_from_file('/path/to/contract.json', 'http://dummyprovider.com') +# Doing the request with ruby stdlib, you can use your favourite lib to do the request +response = Net::HTTP.get_response(URI.parse('http://dummyprovider.com')).body +contract.validate response, body_only: true +``` + +Pacto also has the ability to match a request signature to a contract that is currently in used, via ```Pacto.contract_for request_signature``` + ## Auto-Generated Stubs Pacto provides an API to be used in the consumer's acceptance tests. It uses a custom JSON Schema parser and generator to generate a valid JSON document as the response body, and relies on [WebMock](https://github.com/bblimke/webmock) to stub any HTTP requests made by your application. Important: the JSON generator is in very early stages and does not work with the entire JSON Schema specification. -First, register the contracts that are going to be used in the acceptance tests suite: +First, register the contracts that are going to be used in the acceptance tests suite. The register_contract method accepts zero or more tags: +```ruby +require 'pacto' - require 'pacto' - - contract = Pacto.build_from_file('/path/to/contract.json', 'http://dummyprovider.com') - Pacto.register('my_contract', contract) - +contract1 = Pacto.build_from_file('/path/to/contract1.json', 'http://dummyprovider.com') +contract2 = Pacto.build_from_file('/path/to/contract2.json', 'http://dummyprovider.com') +contract3 = Pacto.build_from_file('/path/to/contract3.json', 'http://dummyprovider.com') +Pacto.register_contract(contract1) +Pacto.register_contract(contract2, :public_api) +Pacto.register_contract(contract3, :public_api, :wip) +``` Then, in the setup phase of the test, specify which contracts will be used for that test: - - Pacto.use('my_contract') - +```ruby +Pacto.use('my_tag') +``` If default values are not specified in the contract's response body, a default value will be automatically generated. It is possible to overwrite those values, however, by passing a second argument: - - Pacto.use('my_contract', :value => 'new value') - +```ruby +Pacto.use('my_tag', :value => 'new value') +``` The values are merged using [hash-deep-merge](https://github.com/Offirmo/hash-deep-merge). - -## Code status - -[![Build Status](https://travis-ci.org/thoughtworks/pacto.png)](https://travis-ci.org/thoughtworks/pacto) -[![Code Climate](https://codeclimate.com/github/thoughtworks/pacto.png)](https://codeclimate.com/github/thoughtworks/pacto) -[![Dependency Status](https://gemnasium.com/thoughtworks/pacto.png)](https://gemnasium.com/thoughtworks/pacto) -[![Coverage Status](https://coveralls.io/repos/thoughtworks/pacto/badge.png)](https://coveralls.io/r/thoughtworks/pacto) ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`)