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`)