quiz_api_client 2.4.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f109a4af811b6581467d20b04bc580c1f2a3c209
4
- data.tar.gz: 73ffe5b91db4ffa77db9de146b29c8162aaef2db
3
+ metadata.gz: b2a00510f91eb1597a6677ddd7db7342293cbead
4
+ data.tar.gz: c1328d1480d86fa91731d575eadd820038ac51d5
5
5
  SHA512:
6
- metadata.gz: 355d7520d371d4cf3a19cb42def9ff1eee21e70eefe6e001b2e0558d6a26dfca1abd9a48d9c184f33ff2bf4ec0d338497729acfa749d73736c490106018509ed
7
- data.tar.gz: f99bbc820678763fd8caee43d27ea3ee78f6bb02591c3a0bc833889d754421b088a7b218615ea9940b97bc7dbf94cf2073105772fcf1c8dcfe4bcd3ff5fafdda
6
+ metadata.gz: 1a3445f192bd75c78fdd3f42f46c2d254ab191bbb9e7c805b77da90244072b8d1467d0001af3591187f8257558bb1adb00e4d5e85c4018cbe180b77e33fc3d5e
7
+ data.tar.gz: 7eb2997e14243ce80868d28995892c7aeb73f85807c16e3e6f98a1017f7dc33365c29199892c3d4fbd95a9669ff434d387cb99e0fd92ef6dfb0a2e501a143a71
data/README.md CHANGED
@@ -179,3 +179,53 @@ Then, run `rake spec` to run the tests.
179
179
  You can also run `rake console` for an interactive prompt that will allow you to experiment.
180
180
 
181
181
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
182
+
183
+ When you add or modify a service, be sure to add or modify contract tests!
184
+
185
+ ## Contract Tests
186
+
187
+ We use [Pact](https://docs.pact.io/) for our contract testing. To generate
188
+ a Pact file, run `bin/contracts`.
189
+
190
+ The `bin/contracts` script will generate the Pact file and place it in the
191
+ pacts/ directory. It will also attempt to publish the Pact file to a local
192
+ Pact Broker.
193
+
194
+ ### Development Workflow:
195
+
196
+ 1. In the quiz_api repo, spin up the Quiz API service with `bin/dev-setup`
197
+ 2. In the quiz_pact_broker repo, spin up a Pact Broker with `bin/dev-setup`
198
+ 3. In the quiz_api repo, write Pact provider states in the
199
+ spec/service_consumers/quiz_api_client_ruby/ directory as needed
200
+ 4. In this repo's spec/contracts/ directory, write or modify a contract test
201
+ 5. In this repo, run `bin/contracts` to generate a Pact file and publish it to
202
+ the Pact Broker
203
+ 6. In the quiz_api repo, run `bin/contracts` to pull the new Pact file from
204
+ the Pact Broker and run the updated contract tests against the Quiz API service
205
+
206
+ Bonus: You can view your Pact file in the Pact Broker at http://pact-broker.docker
207
+ along with some cool goodies!
208
+
209
+ ### Debugging Failures
210
+
211
+ Pact has some basic RSpec output for failed specs. It also keeps a log in
212
+ `log/pact.log` and offers general pointers for debugging.
213
+
214
+ Above all, learn the Pact [basics](https://docs.pact.io/documentation/matching.html).
215
+
216
+ ### What should contract tests cover?
217
+
218
+ The aim of contract testing here is *not* to test all functional requirements
219
+ of the Quiz API service. Rather, the goal is to ensure changes to the Quiz API
220
+ service don't break its clients. We can best accomplish this with the
221
+ following contract test coverage:
222
+
223
+ - Basic happy path requests for all endpoints (POST, GET, PUT, DELETE)
224
+ - Basic error paths for all endpoints (verify the error messages and/or HTTP
225
+ response codes are accurate)
226
+ - Resource state management; for example, when a quiz attempt is submitted but
227
+ not yet graded
228
+ - Special edge case errors
229
+
230
+ Again, what *not* to test: the functional behavior of the service; for
231
+ example, a series of sequential API calls to test a full user scenario.
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'pact_broker/client/tasks'
2
3
  require 'rspec/core/rake_task'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
@@ -17,3 +18,34 @@ task :console do
17
18
  ARGV.clear
18
19
  Pry.start
19
20
  end
21
+
22
+ # see https://github.com/pact-foundation/pact_broker-client/blob/master/README.md
23
+ PactBroker::Client::PublicationTask.new(:local) do |task|
24
+ require 'quiz_api_client'
25
+
26
+ task.consumer_version = QuizApiClient::VERSION
27
+ task.pattern = 'pacts/*.json'
28
+
29
+ task.pact_broker_base_url = 'http://pact-broker.docker'
30
+ task.pact_broker_basic_auth = { username: 'pact', password: 'broker' }
31
+
32
+ # tag the pact with the git branch name
33
+ task.tag = `git rev-parse --abbrev-ref HEAD`.strip
34
+ puts "Pact file tagged with: #{task.tag}"
35
+ end
36
+
37
+ PactBroker::Client::PublicationTask.new(:jenkins_post_merge) do |task|
38
+ require 'quiz_api_client'
39
+
40
+ task.consumer_version = QuizApiClient::VERSION
41
+ task.pattern = 'pacts/*.json'
42
+
43
+ task.pact_broker_base_url = ENV.fetch('PACT_BROKER_BASE_URL')
44
+ task.pact_broker_basic_auth = {
45
+ username: ENV.fetch('PACT_BROKER_BASIC_AUTH_USERNAME'),
46
+ password: ENV.fetch('PACT_BROKER_BASIC_AUTH_PASSWORD')
47
+ }
48
+
49
+ task.tag = 'master'
50
+ puts "Pact file tagged with: #{task.tag}"
51
+ end
data/bin/contracts CHANGED
@@ -4,16 +4,18 @@ function print_results() {
4
4
  exit_code=$?
5
5
  set +e
6
6
 
7
- docker-compose rm -fv contracts-testrunner
8
-
9
7
  if [[ "$exit_code" == "0" ]]; then
10
- echo ""
11
- echo "Success!"
8
+ echo "Success! Open http://pact-broker.docker to view your published pact file."
9
+ else
10
+ echo "Oops! Something went wrong."
12
11
  fi
12
+
13
+ docker cp contracts:/usr/src/app/log . &> /dev/null
14
+ docker cp contracts:/usr/src/app/pacts . &> /dev/null
15
+
16
+ docker-compose rm -fv contracts-testrunner &> /dev/null
13
17
  }
14
18
  trap print_results INT TERM EXIT
15
19
  set -e
16
20
 
17
- docker-compose run --name contracts contracts-testrunner bundle && bundle exec rspec spec/contracts
18
- docker cp contracts:/usr/src/app/log .
19
- docker cp contracts:/usr/src/app/pacts .
21
+ docker-compose run --name contracts contracts-testrunner bash -c "bundle && bundle exec rspec spec/contracts && bundle exec rake pact:publish:local"
data/build.sh CHANGED
@@ -2,11 +2,15 @@
2
2
 
3
3
  set -ex
4
4
 
5
- function save_pact_files_to_s3()
5
+ function publish_pact_file_to_pact_broker()
6
6
  {
7
- echo "Saving pact files to S3..."
8
- folder=${1:-latest}
9
- aws s3 cp pacts s3://ci-asset-cache/pacts/${JOB_NAME}/${folder} --recursive --only-show-errors --region us-east-1
7
+ echo "Publishing pact file to Pact Broker..."
8
+
9
+ docker-compose run --rm \
10
+ -e PACT_BROKER_BASE_URL=${PACT_BROKER_BASE_URL} \
11
+ -e PACT_BROKER_BASIC_AUTH_USERNAME=${PACT_BROKER_BASIC_AUTH_USERNAME} \
12
+ -e PACT_BROKER_BASIC_AUTH_PASSWORD=${PACT_BROKER_BASIC_AUTH_PASSWORD} \
13
+ contracts-testrunner bundle exec rake pact:publish:jenkins_post_merge
10
14
  }
11
15
 
12
16
  function cleanup() {
@@ -23,12 +27,13 @@ docker-compose build --pull
23
27
  echo "Running test suite..."
24
28
  docker-compose run --name coverage testrunner $@
25
29
 
26
- echo ""
30
+ echo
27
31
  echo "Running contract tests..."
28
32
  docker-compose run --name contracts -T contracts-testrunner bundle exec rspec spec/contracts
29
33
  docker cp contracts:/usr/src/app/pacts .
30
34
  docker cp contracts:/usr/src/app/log .
35
+ echo
31
36
 
32
37
  if [[ "${GERRIT_EVENT_TYPE}" == "change-merged" ]]; then
33
- save_pact_files_to_s3
38
+ publish_pact_file_to_pact_broker
34
39
  fi
@@ -3,8 +3,13 @@ version: '2'
3
3
  services:
4
4
  testrunner:
5
5
  volumes:
6
- - .:/usr/src/app/
6
+ - .:/app
7
+ - bundler-config:/home/docker/.rvm/gems/ruby-2.4.0
7
8
 
8
9
  contracts-testrunner:
9
10
  volumes:
10
- - .:/usr/src/app/
11
+ - .:/app
12
+ - bundler-config:/home/docker/.rvm/gems/ruby-2.4.0
13
+
14
+ volumes:
15
+ bundler-config: {}
data/docker-compose.yml CHANGED
@@ -8,3 +8,8 @@ services:
8
8
  build:
9
9
  context: .
10
10
  dockerfile: Dockerfile.contracts
11
+ volumes:
12
+ - pacts:/usr/src/app/pacts
13
+
14
+ volumes:
15
+ pacts: {}
@@ -15,25 +15,31 @@ module QuizApiClient
15
15
  initialize_logger(log_level) if logging
16
16
  end
17
17
 
18
+ def url_for(path)
19
+ url = URI(uri)
20
+ url.path = path
21
+ url.to_s
22
+ end
23
+
18
24
  def get(path, all: false, query: {})
19
- return make_request :get, path, query: query unless all
20
- make_paginated_request :get, path, query: query
25
+ return make_request :get, url_for(path), query: query unless all
26
+ make_paginated_request :get, url_for(path), query: query
21
27
  end
22
28
 
23
29
  def post(path, body = {})
24
- make_request :post, path, body: body.to_json
30
+ make_request :post, url_for(path), body: body.to_json
25
31
  end
26
32
 
27
33
  def patch(path, body = {})
28
- make_request :patch, path, body: body.to_json
34
+ make_request :patch, url_for(path), body: body.to_json
29
35
  end
30
36
 
31
37
  def put(path, body = {})
32
- make_request :put, path, body: body.to_json
38
+ make_request :put, url_for(path), body: body.to_json
33
39
  end
34
40
 
35
41
  def delete(path)
36
- make_request :delete, path
42
+ make_request :delete, url_for(path)
37
43
  end
38
44
 
39
45
  private
@@ -65,24 +71,24 @@ module QuizApiClient
65
71
  end
66
72
  end
67
73
 
68
- def make_request(method, path, request_options = {})
74
+ def make_request(method, url, request_options = {})
69
75
  self.class.send(
70
76
  method,
71
- "#{uri}#{path}",
77
+ url,
72
78
  default_request_data.merge(request_options)
73
79
  )
74
80
  rescue HTTParty::Error, Errno::ECONNREFUSED, Net::ReadTimeout => e
75
81
  raise RequestFailed, e.message
76
82
  end
77
83
 
78
- def make_paginated_request(method, path, request_options)
84
+ def make_paginated_request(method, url, request_options)
79
85
  entities = []
80
- request_path = path
86
+ request_url = url
81
87
 
82
- until request_path.nil? do
83
- resp = make_request(method, request_path, request_options)
88
+ until request_url.nil? do
89
+ resp = make_request(method, request_url, request_options)
84
90
  entities.concat(resp.parsed_response)
85
- request_path = next_page(resp)
91
+ request_url = next_page(resp)
86
92
  end
87
93
  entities
88
94
  end
@@ -1,3 +1,3 @@
1
1
  module QuizApiClient
2
- VERSION = '2.4.0'.freeze
2
+ VERSION = '2.4.1'.freeze
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require 'httparty'
2
2
  require 'jwt'
3
+ require 'link_header'
3
4
 
4
5
  module QuizApiClient
5
6
  class Client
@@ -48,7 +48,8 @@ Gem::Specification.new do |spec|
48
48
  spec.add_development_dependency 'bundler', '~> 1.12'
49
49
  spec.add_development_dependency 'simplecov'
50
50
  spec.add_development_dependency 'webmock'
51
- spec.add_development_dependency 'pact', '~> 1.12.0'
51
+ spec.add_development_dependency 'pact', '~> 1.16.0'
52
+ spec.add_development_dependency 'pact_broker-client', '~> 1.6.0'
52
53
  spec.add_development_dependency 'rake', '~> 10.0'
53
54
  spec.add_development_dependency 'rspec', '~> 3.0'
54
55
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quiz_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wang
@@ -19,7 +19,7 @@ authors:
19
19
  autorequire:
20
20
  bindir: exe
21
21
  cert_chain: []
22
- date: 2017-09-28 00:00:00.000000000 Z
22
+ date: 2017-11-10 00:00:00.000000000 Z
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
25
25
  name: httparty
@@ -111,14 +111,28 @@ dependencies:
111
111
  requirements:
112
112
  - - "~>"
113
113
  - !ruby/object:Gem::Version
114
- version: 1.12.0
114
+ version: 1.16.0
115
115
  type: :development
116
116
  prerelease: false
117
117
  version_requirements: !ruby/object:Gem::Requirement
118
118
  requirements:
119
119
  - - "~>"
120
120
  - !ruby/object:Gem::Version
121
- version: 1.12.0
121
+ version: 1.16.0
122
+ - !ruby/object:Gem::Dependency
123
+ name: pact_broker-client
124
+ requirement: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: 1.6.0
129
+ type: :development
130
+ prerelease: false
131
+ version_requirements: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: 1.6.0
122
136
  - !ruby/object:Gem::Dependency
123
137
  name: rake
124
138
  requirement: !ruby/object:Gem::Requirement
@@ -219,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
233
  version: '0'
220
234
  requirements: []
221
235
  rubyforge_project:
222
- rubygems_version: 2.6.13
236
+ rubygems_version: 2.5.1
223
237
  signing_key:
224
238
  specification_version: 4
225
239
  summary: Ruby client for quiz_api