pact 1.0.11 → 1.0.12
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -2
- data/Gemfile.lock +4 -4
- data/README.md +57 -49
- data/lib/pact/configuration.rb +17 -7
- data/lib/pact/version.rb +1 -1
- data/spec/lib/pact/configuration_spec.rb +45 -9
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
### 1.0.
|
1
|
+
### 1.0.12 (9 October 2013)
|
2
|
+
|
3
|
+
* Changing default pactfile_write_mode to :overwrite, and adding :smart option to dynamically determine whether rake is running. [Beth Skurrie]
|
4
|
+
|
5
|
+
### 1.0.11 (26 September 2013)
|
2
6
|
* Added X-Pact-Mock-Service headers to all mock service administration requests, reducing the risk of the client project making a request that is unintentionally intercepted by the mock service administration handlers. [Beth Skurrie]
|
3
7
|
|
4
|
-
### 1.0.10 (24 September
|
8
|
+
### 1.0.10 (24 September 2013)
|
5
9
|
* Removing unused requires [Beth Skurrie, 20 hours ago]
|
6
10
|
* Adding example changes [Beth Skurrie, 20 hours ago]
|
7
11
|
* Cleaning up provider configuration DSL. [Beth Skurrie, 6 days ago]
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pact (1.0.
|
4
|
+
pact (1.0.12)
|
5
5
|
awesome_print (~> 1.1.0)
|
6
6
|
find_a_port (~> 1.0.1)
|
7
7
|
json
|
@@ -52,10 +52,10 @@ GEM
|
|
52
52
|
rspec-mocks (2.14.3)
|
53
53
|
safe_yaml (0.9.5)
|
54
54
|
slop (3.4.6)
|
55
|
-
thin (1.
|
55
|
+
thin (1.6.0)
|
56
56
|
daemons (>= 1.0.9)
|
57
|
-
eventmachine (>= 0.
|
58
|
-
rack (>= 1.
|
57
|
+
eventmachine (>= 1.0.0)
|
58
|
+
rack (>= 1.5.0)
|
59
59
|
thor (0.18.1)
|
60
60
|
webmock (1.9.3)
|
61
61
|
addressable (>= 2.2.7)
|
data/README.md
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
Define a pact between service consumers and providers.
|
4
4
|
|
5
5
|
|
6
|
-
Pact provides an RSpec DSL for service consumers to define the request they will make to a service service provider and the
|
7
|
-
response they expect back. This expectation is used in the consumers specs to provide a mock service provider, and is also
|
8
|
-
played back in the service provider specs to ensure the service provider actually does provide the response the consumer expects.
|
6
|
+
Pact provides an RSpec DSL for service consumers to define the request they will make to a service service provider and the response they expect back. This expectation is used in the consumers specs to provide a mock service provider, and is also played back in the service provider specs to ensure the service provider actually does provide the response the consumer expects.
|
9
7
|
|
10
8
|
This allows you to test both sides of an integration point using fast unit tests.
|
11
9
|
|
@@ -25,9 +23,7 @@ Put it in your Gemfile. You know how.
|
|
25
23
|
|
26
24
|
## Usage
|
27
25
|
|
28
|
-
###
|
29
|
-
|
30
|
-
#### Configuration
|
26
|
+
### Configuration
|
31
27
|
|
32
28
|
```ruby
|
33
29
|
Pact.configure do | config |
|
@@ -35,68 +31,73 @@ Pact.configure do | config |
|
|
35
31
|
config.log_dir = "???" # Optional, default is ./log
|
36
32
|
config.logger = "??" # Optional, defaults to a file logger to the configured log_dir.
|
37
33
|
config.logger.level = Logger::DEBUG #By default this is INFO, bump this up to debug for more detailed logs
|
38
|
-
# Optional.
|
39
|
-
# The default pactfile_write_mode is "defined?(Rake) ? :overwrite : :update"
|
40
|
-
# This allows it to create a clean file when running rake, but only update the executed interactions when running a specific test using "rspec spec/...".
|
41
|
-
# This is the recommended setting.
|
42
|
-
config.pactfile_write_mode = :ovewrite / :update
|
34
|
+
config.pactfile_write_mode = :ovewrite / :update / :smart # Optional. The default pactfile_write_mode is :overwrite. See notes in Advanced section for further information.
|
43
35
|
end
|
44
36
|
```
|
45
37
|
|
46
|
-
|
38
|
+
### Service Consumer project
|
39
|
+
|
40
|
+
#### Create a Consumer Driven Contract (pact file) using the spec for your client class
|
47
41
|
|
48
42
|
```ruby
|
49
|
-
require 'pact/consumer/rspec'
|
50
43
|
|
51
|
-
class
|
44
|
+
# Imagine a service provider client class that looks something like this
|
45
|
+
|
46
|
+
class MyServiceProviderClient
|
52
47
|
include HTTParty
|
53
|
-
|
54
|
-
base_uri App.configuration.some_service_base_uri
|
48
|
+
base_uri 'http://my-service'
|
55
49
|
|
56
|
-
def
|
57
|
-
JSON.parse(self.class.get("/something").body)
|
50
|
+
def get_text_from_something
|
51
|
+
JSON.parse(self.class.get("/something").body)['text']
|
58
52
|
end
|
59
53
|
end
|
60
54
|
|
61
|
-
|
62
|
-
|
55
|
+
# The following code creates a service on localhost:1234 which will respond to your application's queries
|
56
|
+
# over HTTP as if it were the real "My Service Provider" app. It also creats a mock service provider object
|
57
|
+
# which you will use to set up your expectations. The method name to access the mock service provider
|
58
|
+
# will be what ever name you give as the service argument - in this case "my_service_provider"
|
59
|
+
|
60
|
+
require 'pact/consumer/rspec'
|
61
|
+
|
62
|
+
Pact.service_consumer "My Service Consumer" do
|
63
|
+
has_pact_with "My Service Provider" do
|
63
64
|
mock_service :my_service_provider do
|
64
65
|
port 1234
|
65
66
|
end
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
69
|
-
# The following block creates a service on localhost:1234 which will respond to your application's queries
|
70
|
-
# over HTTP as if it were the real "My Provider" app. It also creats a mock service provider object
|
71
|
-
# which you will use to set up your expectations. The method name to access the mock service provider
|
72
|
-
# will be what ever name you give as the service argument - in this case "my_service_provider"
|
73
|
-
|
74
|
-
|
75
70
|
# Use the :pact => true describe metadata to include all the pact generation functionality in your spec.
|
76
71
|
|
77
|
-
describe
|
72
|
+
describe MyServiceProviderClient, :pact => true do
|
78
73
|
|
79
74
|
before do
|
80
75
|
# Configure your client to point to the stub service on localhost using the port you have specified
|
81
|
-
|
76
|
+
MyServiceProviderClient.base_uri 'localhost:1234'
|
82
77
|
end
|
83
78
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
79
|
+
describe "get_text_from_something" do
|
80
|
+
before do
|
81
|
+
my_service_provider.
|
82
|
+
.given("something exists")
|
83
|
+
.upon_receiving("a request for something")
|
84
|
+
.with( method: :get, path: '/something' )
|
85
|
+
.will_respond_with(
|
86
|
+
status: 200,
|
87
|
+
headers: { 'Content-Type' => 'application/json' },
|
88
|
+
body: {text: 'A thing!', something_else: 'Woot!'}
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "returns the text from something" do
|
93
|
+
# Use your service's client to make the request, rather than hand crafting a HTTP request,
|
94
|
+
# so that you can be sure that the request that will be recorded in the pact file
|
95
|
+
# is one that is actually made by your app.
|
96
|
+
expect(MyServiceProviderClient.get_text_from_something).to eql("A thing!")
|
97
|
+
end
|
98
|
+
|
99
99
|
end
|
100
|
+
|
100
101
|
end
|
101
102
|
|
102
103
|
```
|
@@ -123,13 +124,13 @@ Create a `pact_helper.rb` in your service provider project. The file must be cal
|
|
123
124
|
require 'my_app' # Require the boot files for your app
|
124
125
|
require 'provider_states_for_my_consumer' # See next section on setting up provider states
|
125
126
|
|
126
|
-
Pact.service_provider "My Provider" do
|
127
|
+
Pact.service_provider "My Service Provider" do
|
127
128
|
app { MyApp.new }
|
128
129
|
|
129
|
-
honours_pact_with 'My Consumer' do
|
130
|
+
honours_pact_with 'My Service Consumer' do
|
130
131
|
# This example points to a local file, however, on a real project with a continuous
|
131
|
-
# integration box, you
|
132
|
-
# and point
|
132
|
+
# integration box, you would publish your pacts as artifacts,
|
133
|
+
# and point the pact_uri to the pact published by the last successful build.
|
133
134
|
pact_uri '../path-to-your-consumer-project/specs/pacts/my_consumer-my_provider.json'
|
134
135
|
end
|
135
136
|
end
|
@@ -164,7 +165,7 @@ To define service provider states that create the right data for "a thing exists
|
|
164
165
|
# for it to correctly find these provider states.
|
165
166
|
# Make sure the provider states are included in or required by your pact_helper.rb file.
|
166
167
|
|
167
|
-
Pact.provider_states_for 'My Consumer' do
|
168
|
+
Pact.provider_states_for 'My Service Consumer' do
|
168
169
|
provider_state "a thing exists" do
|
169
170
|
set_up do
|
170
171
|
# Create a thing here using your factory of choice
|
@@ -189,7 +190,8 @@ If a state should be used for all consumers, the top level Pact.with_consumer ca
|
|
189
190
|
#### Verify that the service provider honours the pact
|
190
191
|
|
191
192
|
```ruby
|
192
|
-
#In your Rakefile
|
193
|
+
# In your Rakefile
|
194
|
+
# If the pact gem is in the test/development section of your Gemfile, you may want to put an env check around this so it doesn't load the pact tasks in prod.
|
193
195
|
require 'pact/tasks'
|
194
196
|
```
|
195
197
|
|
@@ -231,6 +233,12 @@ A pact service can be run locally and is really useful for debugging purposes.
|
|
231
233
|
The service prints messages it recieves to stdout which can be really useful
|
232
234
|
when diagnosing issues with pacts.
|
233
235
|
|
236
|
+
## Advanced
|
237
|
+
|
238
|
+
### Notes on pact file write mode
|
239
|
+
|
240
|
+
By default, the pact file will be overwritten (started from scratch) every time any rspec runs any spec using pacts. This means that if there are interactions that haven't been executed in the most recent rspec run, they are effectively removed from the pact file. If you have long running pact specs (e.g. they are generated using the browser with Capybara) and you are developing both consumer and provider in parallel, or trying to fix a broken interaction, it can be tedius to run all the specs at once. In this scenario, you can set the pactfile_write_mode to :update. This will keep all existing interactions, and update only the changed ones, identified by description and provider state. The down side of this is that if either of those fields change, the old interactions will not be removed from the pact file. As a middle path, you can set pactfile_write_mode to :smart. This will use :overwrite mode when running rake (as determined by a call to system using 'ps') and :update when running an individual spec.
|
241
|
+
|
234
242
|
## TODO
|
235
243
|
|
236
244
|
Short term:
|
data/lib/pact/configuration.rb
CHANGED
@@ -8,12 +8,27 @@ module Pact
|
|
8
8
|
attr_accessor :log_dir
|
9
9
|
attr_accessor :logger
|
10
10
|
attr_accessor :tmp_dir
|
11
|
-
attr_accessor :pactfile_write_mode
|
12
11
|
attr_accessor :reports_dir
|
12
|
+
attr_writer :pactfile_write_mode
|
13
13
|
|
14
14
|
def log_path
|
15
15
|
log_dir + "/pact_gem.log"
|
16
16
|
end
|
17
|
+
|
18
|
+
def pactfile_write_mode
|
19
|
+
if @pactfile_write_mode == :smart
|
20
|
+
is_rake_running? ? :overwrite : :update
|
21
|
+
else
|
22
|
+
@pactfile_write_mode
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
#Would love a better way of determining this! It sure won't work on windows.
|
29
|
+
def is_rake_running?
|
30
|
+
`ps -ef | grep rake | grep #{Process.ppid} | grep -v 'grep'`.size > 0
|
31
|
+
end
|
17
32
|
end
|
18
33
|
|
19
34
|
def self.configuration
|
@@ -37,16 +52,11 @@ module Pact
|
|
37
52
|
c.tmp_dir = File.expand_path('./tmp/pacts')
|
38
53
|
c.log_dir = default_log_dir
|
39
54
|
c.logger = default_logger c.log_path
|
40
|
-
c.pactfile_write_mode =
|
55
|
+
c.pactfile_write_mode = :overwrite
|
41
56
|
c.reports_dir = File.expand_path('./reports/pacts')
|
42
57
|
c
|
43
58
|
end
|
44
59
|
|
45
|
-
#Would love a better way of determining this! It sure won't work on windows.
|
46
|
-
def self.is_rake_running?
|
47
|
-
`ps -ef | grep rake | grep #{Process.ppid} | grep -v 'grep'`.size > 0
|
48
|
-
end
|
49
|
-
|
50
60
|
def self.default_log_dir
|
51
61
|
File.expand_path("./log")
|
52
62
|
end
|
data/lib/pact/version.rb
CHANGED
@@ -21,15 +21,51 @@ describe Pact do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
describe
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
describe Pact::Configuration do
|
25
|
+
let(:configuration) { Pact::Configuration.new }
|
26
|
+
describe "pactfile_write_mode" do
|
27
|
+
context "when @pactfile_write_mode is :overwrite" do
|
28
|
+
it 'returns :overwrite' do
|
29
|
+
configuration.pactfile_write_mode = :overwrite
|
30
|
+
expect(configuration.pactfile_write_mode).to eq :overwrite
|
31
|
+
end
|
32
|
+
end
|
33
|
+
context "when @pactfile_write_mode is :update" do
|
34
|
+
it 'returns :overwrite' do
|
35
|
+
configuration.pactfile_write_mode = :update
|
36
|
+
expect(configuration.pactfile_write_mode).to eq :update
|
37
|
+
end
|
38
|
+
end
|
39
|
+
context "when @pactfile_write_mode is :smart" do
|
40
|
+
before do
|
41
|
+
configuration.pactfile_write_mode = :smart
|
42
|
+
configuration.should_receive(:is_rake_running?).and_return(is_rake_running)
|
43
|
+
end
|
44
|
+
context "when rake is running" do
|
45
|
+
let(:is_rake_running) { true }
|
46
|
+
it "returns :overwrite" do
|
47
|
+
expect(configuration.pactfile_write_mode).to eq :overwrite
|
48
|
+
end
|
49
|
+
end
|
50
|
+
context "when rake is not running" do
|
51
|
+
let(:is_rake_running) { false }
|
52
|
+
it "returns :update" do
|
53
|
+
expect(configuration.pactfile_write_mode).to eq :update
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
33
57
|
end
|
34
58
|
end
|
59
|
+
describe "default_configuration" do
|
60
|
+
it "should have a default pact_dir" do
|
61
|
+
expect(Pact.configuration.pact_dir).to eql File.expand_path('./spec/pacts')
|
62
|
+
end
|
63
|
+
it "should have a default log_dir" do
|
64
|
+
expect(Pact.configuration.log_dir).to eql File.expand_path('./log')
|
65
|
+
end
|
66
|
+
it "should have a default logger configured" do
|
67
|
+
expect(Pact.configuration.logger).to be_instance_of Logger
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
35
71
|
end
|
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.12
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2013-10-
|
16
|
+
date: 2013-10-10 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: randexp
|