pact 1.0.11 → 1.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,11 @@
1
- ### 1.0.11 (26 September 2014)
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 2014)
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]
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pact (1.0.11)
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.5.1)
55
+ thin (1.6.0)
56
56
  daemons (>= 1.0.9)
57
- eventmachine (>= 0.12.6)
58
- rack (>= 1.0.0)
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
- ### Service Consumer project
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
- #### Create a Consumer (Driven) Contract
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 SomeServiceClient
44
+ # Imagine a service provider client class that looks something like this
45
+
46
+ class MyServiceProviderClient
52
47
  include HTTParty
53
- # Load your base_uri from a stub-able source
54
- base_uri App.configuration.some_service_base_uri
48
+ base_uri 'http://my-service'
55
49
 
56
- def get_something
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
- Pact.service_consumer "My Consumer" do
62
- has_pact_with "My Provider" do
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 "a pact with My Provider", :pact => true do
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
- Application.configuration.stub(:some_service_base_uri).and_return('localhost:1234')
76
+ MyServiceProviderClient.base_uri 'localhost:1234'
82
77
  end
83
78
 
84
- it "returns something when requested" do
85
- my_service_provider.
86
- given("something exists").
87
- upon_receiving("a request for something").
88
- with({ method: :get, path: '/something' }).
89
- will_respond_with({
90
- status: 200,
91
- headers: { 'Content-Type' => 'application/json' },
92
- body: {something: 'A thing!', something_else: 'Woot!'}
93
- })
94
- # Use your service's client to make the request, rather than hand crafting a HTTP request,
95
- # so that you can be sure that the request that you expect to
96
- # be constructed is actually constructed by your client.
97
- # Do a quick sanity test to ensure client passes back the response properly.
98
- expect(SomeServiceClient.get_something).to eql({something: 'A thing!'})
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 could publish your pacts as artifacts,
132
- # and point this to the pact published by the last successful build.
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:
@@ -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 = is_rake_running? ? :overwrite : :update
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
@@ -1,3 +1,3 @@
1
1
  module Pact
2
- VERSION = "1.0.11"
2
+ VERSION = "1.0.12"
3
3
  end
@@ -21,15 +21,51 @@ describe Pact do
21
21
  end
22
22
  end
23
23
 
24
- describe "configuration" do
25
- it "should have a default pact_dir" do
26
- expect(Pact.configuration.pact_dir).to eql File.expand_path('./spec/pacts')
27
- end
28
- it "should have a default log_dir" do
29
- expect(Pact.configuration.log_dir).to eql File.expand_path('./log')
30
- end
31
- it "should have a default logger configured" do
32
- expect(Pact.configuration.logger).to be_instance_of Logger
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.11
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-07 00:00:00.000000000 Z
16
+ date: 2013-10-10 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: randexp