pact 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +23 -9
- data/lib/pact/consumer_contract/interaction.rb +1 -1
- data/lib/pact/matchers/differ.rb +10 -7
- data/lib/pact/matchers/unix_diff_formatter.rb +8 -1
- data/lib/pact/reification.rb +5 -5
- data/lib/pact/version.rb +1 -1
- data/pact.gemspec +1 -1
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +14 -0
- data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +9 -8
- data/spec/lib/pact/reification_spec.rb +12 -0
- metadata +5 -5
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@ Do this to generate your change history
|
|
2
2
|
|
3
3
|
git log --pretty=format:' * %h - %s (%an, %ad)'
|
4
4
|
|
5
|
+
### 1.3.3 (23 September 2014)
|
6
|
+
|
7
|
+
* 9106aac - Fixed reification when using FactoryGirl. (bethesque, Tue Sep 23 08:23:51 2014 +1000)
|
8
|
+
* 2182803 - Added "query" to example. (bethesque, Fri Sep 19 14:29:36 2014 +1000)
|
9
|
+
* 0002014 - Added key to explain - and + in unix diff output. (bethesque, Mon Sep 8 15:21:37 2014 +1000)
|
10
|
+
* 34f1c9b - Adding forward compatibility for reading 'providerState' from pact. (bethesque, Mon Aug 25 16:09:57 2014 +1000)
|
11
|
+
|
5
12
|
### 1.3.2 (20 August 2014)
|
6
13
|
|
7
14
|
* 65e1e23 - Renamed memoised :options to :diff_options because it clashes with the HTTP options method (bethesque, Wed Aug 20 09:31:0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Define a pact between service consumers and providers, enabling "consumer driven contract" testing.
|
4
4
|
|
5
|
-
Pact provides an
|
5
|
+
Pact provides an fluent API for service consumers to define the HTTP requests they will make to a service provider and the HTTP responses they expect back. These expectations are used in the consumer 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.
|
6
6
|
|
7
7
|
This allows testing of both sides of an integration point using fast unit tests.
|
8
8
|
|
9
|
-
This gem is inspired by the concept of "Consumer driven contracts". See http://martinfowler.com/articles/consumerDrivenContracts.html for more information.
|
9
|
+
This gem is inspired by the concept of "Consumer driven contracts". See [this article](http://martinfowler.com/articles/consumerDrivenContracts.html) by Martin Fowler for more information.
|
10
10
|
|
11
11
|
Travis CI Status: [![travis-ci.org Build Status](https://travis-ci.org/realestate-com-au/pact.png)](https://travis-ci.org/realestate-com-au/pact)
|
12
12
|
|
13
13
|
## What is it good for?
|
14
14
|
|
15
|
-
Pact is most valuable for designing and testing integrations where you (or your team/organisation/partner organisation) control the development of both the consumer and the provider. It is fantastic tool for intra-organsation microservices.
|
15
|
+
Pact is most valuable for designing and testing integrations where you (or your team/organisation/partner organisation) control the development of both the consumer and the provider. It is fantastic tool for testing intra-organsation microservices.
|
16
16
|
|
17
17
|
## What is it not good for?
|
18
18
|
|
@@ -25,10 +25,11 @@ Pact is most valuable for designing and testing integrations where you (or your
|
|
25
25
|
* A service is mocked using an actual process running on a specified port, so javascript clients can be tested as easily as backend clients.
|
26
26
|
* "Provider states" (similar to fixtures) allow the same request to be made with a different expected response.
|
27
27
|
* 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.
|
28
|
+
* RSpec and Minitest support for the service consumer codebase.
|
28
29
|
* Rake tasks allow pacts to be verified against a service provider codebase.
|
29
30
|
* Different versions of a consumer/provider pairs can be easily tested against each other, allowing confidence when deploying new versions of each (see the pact_broker and pact_broker-client gems).
|
30
31
|
* Autogenerated API documentation - need we say more?
|
31
|
-
*
|
32
|
+
* Autogenerated network diagrams with the [Pact Broker](https://github.com/bethesque/pact_broker)
|
32
33
|
|
33
34
|
## How does it work?
|
34
35
|
|
@@ -81,6 +82,8 @@ end
|
|
81
82
|
Imagine a service provider client class that looks something like this.
|
82
83
|
|
83
84
|
```ruby
|
85
|
+
require 'httparty'
|
86
|
+
|
84
87
|
class MyServiceProviderClient
|
85
88
|
include HTTParty
|
86
89
|
base_uri 'http://my-service'
|
@@ -99,6 +102,7 @@ The following code will create a mock service on localhost:1234 which will respo
|
|
99
102
|
# In /spec/service_providers/pact_helper.rb
|
100
103
|
|
101
104
|
require 'pact/consumer/rspec'
|
105
|
+
# or require 'pact/consumer/minitest' if you are using Minitest
|
102
106
|
|
103
107
|
Pact.service_consumer "My Service Consumer" do
|
104
108
|
has_pact_with "My Service Provider" do
|
@@ -114,7 +118,9 @@ end
|
|
114
118
|
```ruby
|
115
119
|
# In /spec/service_providers/my_service_provider_client_spec.rb
|
116
120
|
|
117
|
-
#
|
121
|
+
# When using RSpec, use the metadata `:pact => true` to include all the pact functionality in your spec.
|
122
|
+
# When using Minitest, include Pact::Consumer::Minitest in your spec.
|
123
|
+
|
118
124
|
describe MyServiceProviderClient, :pact => true do
|
119
125
|
|
120
126
|
before do
|
@@ -128,7 +134,7 @@ describe MyServiceProviderClient, :pact => true do
|
|
128
134
|
|
129
135
|
before do
|
130
136
|
my_service_provider.given("something exists").
|
131
|
-
upon_receiving("a request for something").with(method: :get, path: '/something').
|
137
|
+
upon_receiving("a request for something").with(method: :get, path: '/something', query: '').
|
132
138
|
will_respond_with(
|
133
139
|
status: 200,
|
134
140
|
headers: {'Content-Type' => 'application/json'},
|
@@ -167,14 +173,18 @@ end
|
|
167
173
|
|
168
174
|
#### 7. Run the specs again.
|
169
175
|
|
170
|
-
Green! You now have a pact file that can be used to verify your expectations
|
171
|
-
|
176
|
+
Green! You now have a pact file that can be used to verify your expectations of the provider project.
|
177
|
+
|
178
|
+
Now, rinse and repeat for other likely status codes that may be returned. For example, consider how you want your client to respond to a:
|
179
|
+
* 404 (return null, or raise an error?)
|
180
|
+
* 500 (specifying that the response body should contain an error message, and ensuring that your client logs that error message will make your life much easier when things go wrong)
|
181
|
+
* 401/403 if there is authorisation.
|
172
182
|
|
173
183
|
### Service Provider project
|
174
184
|
|
175
185
|
#### 1. Create the skeleton API classes
|
176
186
|
|
177
|
-
Create your API class using the framework of your choice - leave the methods unimplemented, we're doing Test First Develoment, remember?
|
187
|
+
Create your API class using the framework of your choice (the Pact authors have a preference for [Webmachine][webmachine] and [Roar][roar]) - leave the methods unimplemented, we're doing Test First Develoment, remember?
|
178
188
|
|
179
189
|
#### 2. Tell your provider that it needs to honour the pact file you made earlier
|
180
190
|
|
@@ -245,6 +255,7 @@ As in all things, there are good ways to implement Pacts, and there are not so g
|
|
245
255
|
* [Terminology](https://github.com/realestate-com-au/pact/wiki/Terminology)
|
246
256
|
* [Provider States](https://github.com/realestate-com-au/pact/wiki/Provider-states)
|
247
257
|
* [Verifying pacts](https://github.com/realestate-com-au/pact/wiki/Verifying-pacts)
|
258
|
+
* [Sharing pacts between consumer and provider](https://github.com/realestate-com-au/pact/wiki/Sharing-pacts-between-consumer-and-provider)
|
248
259
|
* [Frequently asked questions](https://github.com/realestate-com-au/pact/wiki/FAQ)
|
249
260
|
* [Rarely asked questions](https://github.com/realestate-com-au/pact/wiki/RAQ)
|
250
261
|
* [Best practices](https://github.com/realestate-com-au/pact/wiki/Best-practices)
|
@@ -297,3 +308,6 @@ Long term:
|
|
297
308
|
|
298
309
|
If you would like to implement pact in another language, please check out the [Pact specification](https://github.com/bethesque/pact-specification) and have a chat to one of us on the [pact-dev Google group](https://groups.google.com/forum/#!forum/pact-dev). The vision is to have a compatible pact implementation in all the commonly used languages, your help would be greatly appreciated!
|
299
310
|
|
311
|
+
[webmachine]: https://github.com/seancribbs/webmachine-ruby
|
312
|
+
[roar]: https://github.com/apotonick/roar
|
313
|
+
|
@@ -13,7 +13,7 @@ module Pact
|
|
13
13
|
@description = attributes[:description]
|
14
14
|
@request = attributes[:request]
|
15
15
|
@response = attributes[:response]
|
16
|
-
@provider_state = attributes[:provider_state]
|
16
|
+
@provider_state = attributes[:provider_state] || attributes[:providerState]
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.from_hash hash
|
data/lib/pact/matchers/differ.rb
CHANGED
@@ -71,6 +71,16 @@ module Pact
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
def red(text)
|
75
|
+
return text unless @color
|
76
|
+
color(text, 31)
|
77
|
+
end
|
78
|
+
|
79
|
+
def green(text)
|
80
|
+
return text unless @color
|
81
|
+
color(text, 32)
|
82
|
+
end
|
83
|
+
|
74
84
|
protected
|
75
85
|
|
76
86
|
def format
|
@@ -85,13 +95,6 @@ module Pact
|
|
85
95
|
"\e[#{color_code}m#{text}\e[0m"
|
86
96
|
end
|
87
97
|
|
88
|
-
def red(text)
|
89
|
-
color(text, 31)
|
90
|
-
end
|
91
|
-
|
92
|
-
def green(text)
|
93
|
-
color(text, 32)
|
94
|
-
end
|
95
98
|
|
96
99
|
def blue(text)
|
97
100
|
color(text, 34)
|
@@ -11,6 +11,7 @@ module Pact
|
|
11
11
|
def initialize diff, options = {}
|
12
12
|
@diff = diff
|
13
13
|
@colour = options.fetch(:colour, false)
|
14
|
+
@differ = Pact::Matchers::Differ.new(@colour)
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.call diff, options = {colour: Pact.configuration.color_enabled}
|
@@ -24,7 +25,7 @@ module Pact
|
|
24
25
|
def to_s
|
25
26
|
expected = generate_string(diff, :expected)
|
26
27
|
actual = generate_string(diff, :actual)
|
27
|
-
|
28
|
+
@differ.diff_as_string(actual, expected).lstrip + "\n" + key
|
28
29
|
end
|
29
30
|
|
30
31
|
private
|
@@ -85,6 +86,12 @@ module Pact
|
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
89
|
+
def key
|
90
|
+
"Key: " + @differ.red("-") + @differ.red(" means \"expected, but was not found\". \n") +
|
91
|
+
@differ.green(" +") + @differ.green(" means \"actual, should not be found\". \n") +
|
92
|
+
" Values where the expected matches the actual are not shown.\n"
|
93
|
+
end
|
94
|
+
|
88
95
|
class RegexpDecorator
|
89
96
|
|
90
97
|
def initialize regexp
|
data/lib/pact/reification.rb
CHANGED
@@ -4,20 +4,20 @@ module Pact
|
|
4
4
|
module Reification
|
5
5
|
|
6
6
|
def self.from_term(term)
|
7
|
-
case
|
8
|
-
when
|
7
|
+
case term
|
8
|
+
when Pact::Term, Regexp, Pact::SomethingLike
|
9
9
|
term.generate
|
10
|
-
when
|
10
|
+
when Hash
|
11
11
|
term.inject({}) do |mem, (key,term)|
|
12
12
|
mem[key] = from_term(term)
|
13
13
|
mem
|
14
14
|
end
|
15
|
-
when
|
15
|
+
when Array
|
16
16
|
term.inject([]) do |mem, term|
|
17
17
|
mem << from_term(term)
|
18
18
|
mem
|
19
19
|
end
|
20
|
-
when
|
20
|
+
when Pact::Request::Base
|
21
21
|
from_term(term.to_hash)
|
22
22
|
else
|
23
23
|
term
|
data/lib/pact/version.rb
CHANGED
data/pact.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'pact/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "pact"
|
8
8
|
gem.version = Pact::VERSION
|
9
|
-
gem.authors = ["James Fraser", "Sergei Matheson", "Brent Snook", "Ronald Holshausen", "
|
9
|
+
gem.authors = ["James Fraser", "Sergei Matheson", "Brent Snook", "Ronald Holshausen", "Beth Skurrie"]
|
10
10
|
gem.email = ["james.fraser@alumni.swinburne.edu", "sergei.matheson@gmail.com", "brent@fuglylogic.com", "uglyog@gmail.com", "bskurrie@dius.com.au"]
|
11
11
|
gem.description = %q{Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.}
|
12
12
|
gem.summary = %q{Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.}
|
@@ -7,6 +7,9 @@ module Pact
|
|
7
7
|
|
8
8
|
describe Interaction do
|
9
9
|
|
10
|
+
let(:request) { {method: 'get', path: 'path'} }
|
11
|
+
let(:response) { {} }
|
12
|
+
|
10
13
|
describe "==" do
|
11
14
|
subject { InteractionFactory.create }
|
12
15
|
context "when other is the same" do
|
@@ -39,6 +42,17 @@ module Pact
|
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
45
|
+
describe "from_hash" do
|
46
|
+
context "when providerState has been used instead of provider_state" do
|
47
|
+
|
48
|
+
subject { Interaction.from_hash('response' => response, 'request' => request, 'providerState' => 'some state') }
|
49
|
+
|
50
|
+
it "recognises the provider state" do
|
51
|
+
expect(subject.provider_state).to eq 'some state'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
42
56
|
describe "to JSON" do
|
43
57
|
let(:request) do
|
44
58
|
{
|
@@ -9,6 +9,7 @@ module Pact
|
|
9
9
|
|
10
10
|
describe ".call" do
|
11
11
|
|
12
|
+
let(:key_lines_count) { 4 }
|
12
13
|
let(:colour) { false }
|
13
14
|
subject { UnixDiffFormatter.call(diff, {colour: colour}) }
|
14
15
|
|
@@ -54,7 +55,7 @@ EOF
|
|
54
55
|
end
|
55
56
|
|
56
57
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
57
|
-
expect(line_count).to eq 9
|
58
|
+
expect(line_count).to eq 9 + key_lines_count
|
58
59
|
end
|
59
60
|
|
60
61
|
end
|
@@ -76,7 +77,7 @@ EOF
|
|
76
77
|
end
|
77
78
|
|
78
79
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
79
|
-
expect(line_count).to eq 9
|
80
|
+
expect(line_count).to eq 9 + key_lines_count
|
80
81
|
end
|
81
82
|
|
82
83
|
end
|
@@ -98,7 +99,7 @@ EOF
|
|
98
99
|
end
|
99
100
|
|
100
101
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
101
|
-
expect(line_count).to eq 5
|
102
|
+
expect(line_count).to eq 5 + key_lines_count
|
102
103
|
end
|
103
104
|
|
104
105
|
end
|
@@ -120,7 +121,7 @@ EOF
|
|
120
121
|
end
|
121
122
|
|
122
123
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
123
|
-
expect(line_count).to eq 8
|
124
|
+
expect(line_count).to eq 8 + key_lines_count
|
124
125
|
end
|
125
126
|
end
|
126
127
|
|
@@ -140,7 +141,7 @@ EOF
|
|
140
141
|
end
|
141
142
|
|
142
143
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
143
|
-
expect(line_count).to eq 8
|
144
|
+
expect(line_count).to eq 8 + key_lines_count
|
144
145
|
end
|
145
146
|
|
146
147
|
end
|
@@ -159,7 +160,7 @@ EOF
|
|
159
160
|
end
|
160
161
|
|
161
162
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
162
|
-
expect(line_count).to eq 8
|
163
|
+
expect(line_count).to eq 8 + key_lines_count
|
163
164
|
end
|
164
165
|
|
165
166
|
end
|
@@ -185,7 +186,7 @@ EOF
|
|
185
186
|
end
|
186
187
|
|
187
188
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
188
|
-
expect(line_count).to eq 8
|
189
|
+
expect(line_count).to eq 8 + key_lines_count
|
189
190
|
end
|
190
191
|
|
191
192
|
end
|
@@ -203,7 +204,7 @@ EOF
|
|
203
204
|
end
|
204
205
|
|
205
206
|
it "generates the right number of lines, even with ActiveSupport loaded" do
|
206
|
-
expect(line_count).to eq 11
|
207
|
+
expect(line_count).to eq 11 + key_lines_count
|
207
208
|
end
|
208
209
|
|
209
210
|
end
|
@@ -51,5 +51,17 @@ module Pact
|
|
51
51
|
|
52
52
|
end
|
53
53
|
|
54
|
+
context "when SomethingLike" do
|
55
|
+
|
56
|
+
let(:request) { Pact::SomethingLike.new({a: 'String'})}
|
57
|
+
|
58
|
+
subject { Reification.from_term(request)}
|
59
|
+
|
60
|
+
it "returns the contents of the SomethingLike" do
|
61
|
+
expect(subject).to eq({a: 'String'})
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
54
66
|
end
|
55
67
|
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.3.
|
4
|
+
version: 1.3.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
- Sergei Matheson
|
10
10
|
- Brent Snook
|
11
11
|
- Ronald Holshausen
|
12
|
-
-
|
12
|
+
- Beth Skurrie
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2014-
|
16
|
+
date: 2014-09-22 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: randexp
|
@@ -560,7 +560,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
560
560
|
version: '0'
|
561
561
|
segments:
|
562
562
|
- 0
|
563
|
-
hash:
|
563
|
+
hash: 3250914731854232740
|
564
564
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
565
565
|
none: false
|
566
566
|
requirements:
|
@@ -569,7 +569,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
569
569
|
version: '0'
|
570
570
|
segments:
|
571
571
|
- 0
|
572
|
-
hash:
|
572
|
+
hash: 3250914731854232740
|
573
573
|
requirements: []
|
574
574
|
rubyforge_project:
|
575
575
|
rubygems_version: 1.8.23
|