pact 1.0.21 → 1.0.22
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +20 -33
- data/config.ru +3 -0
- data/lib/pact/provider/configuration.rb +11 -2
- data/lib/pact/version.rb +1 -1
- data/spec/lib/pact/provider/configuration_spec.rb +10 -9
- data/spec/support/app_for_config_ru.rb +4 -0
- metadata +6 -3
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@ Do this to generate your change history
|
|
2
2
|
|
3
3
|
git log --date=relative --pretty=format:' * %h - %s (%an, %ad)'
|
4
4
|
|
5
|
+
### 1.0.22 (25 November 2013)
|
6
|
+
|
7
|
+
* f742833 - Updating README (Beth Skurrie, 36 seconds ago)
|
8
|
+
* ec0d9e2 - Refactor config_ru lambda (Beth Skurrie, 8 minutes ago)
|
9
|
+
* 5cb5702 - Added code to use app in config.ru if non is specified as per https://github.com/uglyog/pact/issues/9 (Beth Skurrie, 10 minutes ago)
|
10
|
+
|
5
11
|
### 1.0.21 (25 November 2013)
|
6
12
|
|
7
13
|
* f810795 - add jruby 2.0 to travis (Ronald Holshausen, 4 days ago)
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# Pact
|
2
2
|
|
3
|
-
Define a pact between service consumers and providers.
|
3
|
+
Define a pact between service consumers and providers, enabling "consumer driven contract" testing.
|
4
4
|
|
5
|
+
Pact provides an RSpec DSL for service consumers to define the requests they will make to a service provider and the responses they expect back. These expectations are used in the consumers specs to provide a mock service provider. The interactions are recorded, and played back in the service provider specs to ensure the service provider actually does provide the response the consumer expects.
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
This allows you to test both sides of an integration point using fast unit tests.
|
7
|
+
This allows testing of both sides of an integration point using fast unit tests.
|
9
8
|
|
10
9
|
This gem is inspired by the concept of "Consumer driven contracts". See http://martinfowler.com/articles/consumerDrivenContracts.html for more information.
|
11
10
|
|
@@ -15,9 +14,10 @@ Travis CI Status: [![travis-ci.org Build Status](https://travis-ci.org/uglyog/pa
|
|
15
14
|
* A services is mocked using an actual process running on a specified port, so javascript clients can be tested as easily as backend clients.
|
16
15
|
* "Provider states" (similar to fixtures) allow the same request to be made with a different expected response.
|
17
16
|
* Consumers specify only the fields they are interested in, allowing a provider to return more fields without breaking the pact. This allows a provider to have a different pact with a different consumer, and know which fields each cares about in a given response.
|
18
|
-
* Expected interactions are verified to have actually occurred.
|
19
|
-
*
|
20
|
-
*
|
17
|
+
* Expected interactions are verified to have actually occurred in the consumer specs.
|
18
|
+
* The mocked responses are verified to be valid by replaying the interactions against the provider codebase.
|
19
|
+
* Rake verification tasks allow a pacts at one or more URIs to be checked against a given service provider codebase.
|
20
|
+
* Different versions of a consumer/provider pair can be easily tested against each other, allowing confidence when deploying new versions of each (see the pact_broker and pact_broker-client gems).
|
21
21
|
|
22
22
|
## Installation
|
23
23
|
|
@@ -154,15 +154,23 @@ Create your API class using the framework of your choice (e.g. Sinatra, Grape) -
|
|
154
154
|
Create a `pact_helper.rb` in your service provider project. The file must be called pact_helper.rb, however there is some flexibility in where it can be stored. The recommended place is `specs/service_consumers/pact_helper.rb`.
|
155
155
|
|
156
156
|
```ruby
|
157
|
-
require '
|
157
|
+
require 'pact/provider/rspec'
|
158
|
+
# If you wish to use the same spec_helper file as your unit tests, require it here.
|
159
|
+
# Otherwise, you can set up a separate RSpec configuration in this file just for pact:verify.
|
160
|
+
require './spec_helper'
|
158
161
|
|
159
162
|
Pact.service_provider "My Service Provider" do
|
163
|
+
# If you have a config.ru file, the app will be loaded from it automatically and you can skip the app config.
|
164
|
+
# Otherwise, set your rack app here as you would when using Rack::Test::Methods
|
165
|
+
|
160
166
|
app { MyApp.new }
|
161
167
|
|
162
168
|
honours_pact_with 'My Service Consumer' do
|
169
|
+
|
163
170
|
# This example points to a local file, however, on a real project with a continuous
|
164
171
|
# integration box, you would publish your pacts as artifacts,
|
165
172
|
# and point the pact_uri to the pact published by the last successful build.
|
173
|
+
|
166
174
|
pact_uri '../path-to-your-consumer-project/specs/pacts/my_consumer-my_provider.json'
|
167
175
|
end
|
168
176
|
end
|
@@ -306,33 +314,14 @@ Configure the pact_uri in the Pact.service_provider block with the pact artifact
|
|
306
314
|
|
307
315
|
It should run with all your other tests. If an integration is broken, you want to know about it *before* you check in.
|
308
316
|
|
309
|
-
#### Load your app from the config.ru file
|
310
|
-
|
311
|
-
Your config.ru file may mount your app at a specified path. e.g.
|
312
|
-
|
313
|
-
```
|
314
|
-
run Rack::URLMap.new( '/some-path' => MyServiceProvider::API )
|
315
|
-
```
|
316
|
-
|
317
|
-
To avoid duplicating this code, and potentially letting your tests get out of sync with the config.ru file, you can parse the config.ru file and use the returned app in your service provider definition. e.g.
|
318
|
-
|
319
|
-
```
|
320
|
-
def app_in_config_ru
|
321
|
-
app, options = Rack::Builder.parse_file('config.ru')
|
322
|
-
app
|
323
|
-
end
|
324
|
-
|
325
|
-
Pact.service_provider "My Service Provider" do
|
326
|
-
app { app_in_config_ru }
|
327
|
-
end
|
328
|
-
```
|
329
|
-
|
330
|
-
Be aware that the Rack::Builder.parse_file seems to require files even if they have already been required, so make sure your boot files are idempotent.
|
331
|
-
|
332
317
|
#### Use the real database
|
333
318
|
|
334
319
|
Do not stub your database calls for pact:verify. This is the best time for you to test your database integration. If you stub your database calls, you are getting little more assurance that the real end-to-end will work than if you'd used a unit test. It's the appropriate time to incur the overhead of a database call.
|
335
320
|
|
321
|
+
## Gotchas
|
322
|
+
|
323
|
+
* Be aware when using the app from the config.ru file is used (the default option) that the Rack::Builder.parse_file seems to require files even if they have already been required, so make sure your boot files are idempotent.
|
324
|
+
|
336
325
|
## Advanced
|
337
326
|
|
338
327
|
### Filtering the pact:verify specs
|
@@ -398,8 +387,6 @@ See https://www.relishapp.com/rspec/rspec-core/docs/hooks/filters for more infor
|
|
398
387
|
|
399
388
|
Short term:
|
400
389
|
- FIX EXAMPLE!!!
|
401
|
-
- Make a pact-broker to store and return all the pacts, removing dependency on the CI box URLs.
|
402
|
-
- Provide a better work around for ActiveSupport JSON rubygems hell.
|
403
390
|
|
404
391
|
Long term:
|
405
392
|
- Provide more flexible matching (eg the keys should match, and the classes of the values should match, but the values of each key do not need to be equal). This is to make the pact verification less brittle.
|
data/config.ru
ADDED
@@ -34,6 +34,14 @@ module Pact
|
|
34
34
|
def pact_verifications
|
35
35
|
@pact_verifications ||= []
|
36
36
|
end
|
37
|
+
|
38
|
+
def config_ru_path
|
39
|
+
@config_ru_path ||= './config.ru'
|
40
|
+
end
|
41
|
+
|
42
|
+
def config_ru_path= config_ru_path
|
43
|
+
@config_ru_path = config_ru_path
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
Pact::Configuration.send(:include, ConfigurationExtension)
|
@@ -89,9 +97,11 @@ module Pact
|
|
89
97
|
|
90
98
|
attr_accessor :name, :app_block
|
91
99
|
|
100
|
+
CONFIG_RU_APP = lambda { Rack::Builder.parse_file(Pact.configuration.config_ru_path).first }
|
101
|
+
|
92
102
|
def initialize name
|
93
103
|
@name = name
|
94
|
-
@app_block =
|
104
|
+
@app_block = CONFIG_RU_APP
|
95
105
|
end
|
96
106
|
|
97
107
|
dsl do
|
@@ -117,7 +127,6 @@ module Pact
|
|
117
127
|
|
118
128
|
def validate
|
119
129
|
raise "Please provide a name for the Provider" unless name && !name.strip.empty?
|
120
|
-
raise "Please configure an app for the Provider" unless app_block
|
121
130
|
end
|
122
131
|
|
123
132
|
def create_service_provider
|
data/lib/pact/version.rb
CHANGED
@@ -26,6 +26,16 @@ module Pact::Provider::Configuration
|
|
26
26
|
expect{ Pact.configuration.provider }.to raise_error(/Please configure your provider/)
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
context "when a provider is configured without an app" do
|
31
|
+
before do
|
32
|
+
Pact.service_provider "Fred" do
|
33
|
+
end
|
34
|
+
end
|
35
|
+
it "uses the app from config.ru" do
|
36
|
+
expect( Pact.configuration.provider.app ).to be(AppForConfigRu)
|
37
|
+
end
|
38
|
+
end
|
29
39
|
end
|
30
40
|
|
31
41
|
describe PactVerification do
|
@@ -101,15 +111,6 @@ module Pact::Provider::Configuration
|
|
101
111
|
expect{ subject.send(:validate)}.to raise_error("Please provide a name for the Provider")
|
102
112
|
end
|
103
113
|
end
|
104
|
-
context "when no app is provided" do
|
105
|
-
subject do
|
106
|
-
ServiceProviderDSL.new 'Blah' do
|
107
|
-
end
|
108
|
-
end
|
109
|
-
it "raises an error" do
|
110
|
-
expect{ subject.send(:validate) }.to raise_error("Please configure an app for the Provider")
|
111
|
-
end
|
112
|
-
end
|
113
114
|
end
|
114
115
|
|
115
116
|
describe 'honours_pact_with' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.22
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -279,6 +279,7 @@ files:
|
|
279
279
|
- README.md
|
280
280
|
- Rakefile
|
281
281
|
- bin/pact
|
282
|
+
- config.ru
|
282
283
|
- example/animal-service/Gemfile
|
283
284
|
- example/animal-service/Gemfile.lock
|
284
285
|
- example/animal-service/Rakefile
|
@@ -395,6 +396,7 @@ files:
|
|
395
396
|
- spec/spec_helper.rb
|
396
397
|
- spec/support/a_consumer-a_producer.json
|
397
398
|
- spec/support/a_consumer-a_provider.json
|
399
|
+
- spec/support/app_for_config_ru.rb
|
398
400
|
- spec/support/consumer_contract_template.json
|
399
401
|
- spec/support/dsl_spec_support.rb
|
400
402
|
- spec/support/factories.rb
|
@@ -419,7 +421,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
419
421
|
version: '0'
|
420
422
|
segments:
|
421
423
|
- 0
|
422
|
-
hash:
|
424
|
+
hash: 1182047425998304532
|
423
425
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
424
426
|
none: false
|
425
427
|
requirements:
|
@@ -428,7 +430,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
428
430
|
version: '0'
|
429
431
|
segments:
|
430
432
|
- 0
|
431
|
-
hash:
|
433
|
+
hash: 1182047425998304532
|
432
434
|
requirements: []
|
433
435
|
rubyforge_project:
|
434
436
|
rubygems_version: 1.8.23
|
@@ -475,6 +477,7 @@ test_files:
|
|
475
477
|
- spec/spec_helper.rb
|
476
478
|
- spec/support/a_consumer-a_producer.json
|
477
479
|
- spec/support/a_consumer-a_provider.json
|
480
|
+
- spec/support/app_for_config_ru.rb
|
478
481
|
- spec/support/consumer_contract_template.json
|
479
482
|
- spec/support/dsl_spec_support.rb
|
480
483
|
- spec/support/factories.rb
|