pact 1.0.30 → 1.0.31

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +2 -2
  3. data/Gemfile.lock +0 -7
  4. data/README.md +50 -53
  5. data/Rakefile +1 -25
  6. data/documentation/Testing with pact.png +0 -0
  7. data/documentation/faq.md +45 -0
  8. data/documentation/raq.md +39 -0
  9. data/documentation/terminology.md +25 -0
  10. data/example/animal-service/Gemfile +4 -4
  11. data/example/animal-service/Gemfile.lock +20 -15
  12. data/example/animal-service/Rakefile +1 -1
  13. data/example/animal-service/config.ru +3 -0
  14. data/example/animal-service/db/animal_db.sqlite3 +0 -0
  15. data/example/animal-service/db/animals_db.sqlite3 +0 -0
  16. data/example/animal-service/lib/animal_service/animal_repository.rb +16 -0
  17. data/example/animal-service/lib/animal_service/api.rb +28 -0
  18. data/example/animal-service/lib/animal_service/db.rb +5 -0
  19. data/example/animal-service/spec/service_consumers/pact_helper.rb +10 -16
  20. data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +13 -3
  21. data/example/zoo-app/Gemfile +0 -2
  22. data/example/zoo-app/Gemfile.lock +7 -8
  23. data/example/zoo-app/lib/zoo_app/animal_service_client.rb +8 -4
  24. data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +18 -64
  25. data/example/zoo-app/spec/service_providers/animal_service_client_spec.rb +76 -0
  26. data/example/zoo-app/spec/service_providers/pact_helper.rb +1 -1
  27. data/example/zoo-app/spec/spec_helper.rb +0 -2
  28. data/lib/pact/app.rb +4 -2
  29. data/lib/pact/consumer/configuration.rb +2 -2
  30. data/lib/pact/consumer/consumer_contract_builder.rb +2 -1
  31. data/lib/pact/consumer/interactions_filter.rb +7 -0
  32. data/lib/pact/consumer/mock_service/app.rb +7 -2
  33. data/lib/pact/consumer/mock_service/interaction_mismatch.rb +6 -1
  34. data/lib/pact/consumer/mock_service/interaction_post.rb +1 -1
  35. data/lib/pact/consumer/mock_service/rack_request_helper.rb +1 -1
  36. data/lib/pact/consumer/rspec.rb +9 -15
  37. data/lib/pact/consumer/rspec/full_example_description.rb +28 -0
  38. data/lib/pact/consumer/spec_hooks.rb +31 -0
  39. data/lib/pact/consumer_contract/consumer_contract.rb +2 -31
  40. data/lib/pact/consumer_contract/file_name.rb +13 -0
  41. data/lib/pact/consumer_contract/pact_file.rb +24 -0
  42. data/lib/pact/provider/matchers.rb +3 -1
  43. data/lib/pact/provider/provider_state.rb +43 -20
  44. data/lib/pact/version.rb +1 -1
  45. data/pact.gemspec +0 -1
  46. data/spec/features/consumption_spec.rb +5 -0
  47. data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +162 -147
  48. data/spec/lib/pact/consumer/mock_service/app_spec.rb +52 -0
  49. data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +3 -3
  50. metadata +19 -25
  51. data/example/zoo-app/spec/service_providers/animal_service_spec.rb +0 -92
data/.gitignore CHANGED
@@ -27,3 +27,4 @@ spec/pacts
27
27
  .ruby-version
28
28
  log
29
29
  .idea
30
+ reports
data/.travis.yml CHANGED
@@ -2,7 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.0
5
6
  - jruby-19mode
6
7
  - jruby-20mode
7
- - ruby-head
8
- - jruby-head
8
+ - jruby-head
data/Gemfile.lock CHANGED
@@ -8,7 +8,6 @@ PATH
8
8
  rack-test (~> 0.6.2)
9
9
  randexp (~> 0.1.7)
10
10
  rspec (~> 2.12)
11
- thin
12
11
  thor
13
12
  webrick
14
13
 
@@ -27,9 +26,7 @@ GEM
27
26
  coderay (1.0.9)
28
27
  crack (0.4.1)
29
28
  safe_yaml (~> 0.9.0)
30
- daemons (1.1.9)
31
29
  diff-lcs (1.2.4)
32
- eventmachine (1.0.3)
33
30
  fakefs (0.4.2)
34
31
  find_a_port (1.0.1)
35
32
  hashie (2.0.5)
@@ -59,10 +56,6 @@ GEM
59
56
  rspec-mocks (2.14.3)
60
57
  safe_yaml (0.9.5)
61
58
  slop (3.4.6)
62
- thin (1.6.1)
63
- daemons (>= 1.0.9)
64
- eventmachine (>= 1.0.0)
65
- rack (>= 1.0.0)
66
59
  thor (0.18.1)
67
60
  thread_safe (0.1.3)
68
61
  atomic
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
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
+ Pact provides an RSpec DSL 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 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.
6
6
 
7
7
  This allows testing of both sides of an integration point using fast unit tests.
8
8
 
@@ -17,7 +17,25 @@ Travis CI Status: [![travis-ci.org Build Status](https://travis-ci.org/realestat
17
17
  * Expected interactions are verified to have actually occurred in the consumer specs.
18
18
  * The mocked responses are verified to be valid by replaying the interactions against the provider codebase.
19
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).
20
+ * 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).
21
+
22
+ ## How does it work?
23
+
24
+ 1. In the specs for the provider facing code in the consumer project, expectations are set up on a mock service provider.
25
+ 1. When the specs are run, the requests, and their expected responses, are written to a "pact" file.
26
+ 1. The requests in the pact file are later replayed against the provider, and the actual responses are checked to make sure they match the expected responses.
27
+
28
+ ## Why is developing and testing with pacts better than using integration tests?
29
+
30
+ * Faster execution.
31
+ * No need to manage starting and stopping multiple processes.
32
+ * Reliable responses from mock service provider reduce likelihood of flakey tests.
33
+ * Only one component is being tested at a time, making the causes of test failures easier to identify.
34
+ * Design of service provider is improved by considering first how the data is actually going to be used, rather than how it is most easily retrieved and serialised.
35
+
36
+ ## Google users group
37
+
38
+ https://groups.google.com/forum/#!forum/pact-support
21
39
 
22
40
  ## Installation
23
41
 
@@ -35,12 +53,12 @@ Imagine a model class that looks something like this. The attributes for a Somet
35
53
  class SomethingModel
36
54
  attr_reader :name
37
55
 
38
- def intialize name
56
+ def initialize name
39
57
  @name = name
40
58
  end
41
59
 
42
60
  def == other
43
- other.is_a?(Something) && other.name == name
61
+ other.is_a?(SomethingModel) && other.name == name
44
62
  end
45
63
  end
46
64
  ```
@@ -92,6 +110,8 @@ describe MyServiceProviderClient, :pact => true do
92
110
  # Configure your client to point to the stub service on localhost using the port you have specified
93
111
  MyServiceProviderClient.base_uri 'localhost:1234'
94
112
  end
113
+
114
+ subject { MyServiceProviderClient.new }
95
115
 
96
116
  describe "get_something" do
97
117
  before do
@@ -107,7 +127,7 @@ describe MyServiceProviderClient, :pact => true do
107
127
  end
108
128
 
109
129
  it "returns a Something" do
110
- expect(MyServiceProviderClient.get_something).to eq(SomethingModel.new('A small something'))
130
+ expect(subject.get_something).to eq(SomethingModel.new('A small something'))
111
131
  end
112
132
 
113
133
  end
@@ -201,7 +221,7 @@ Yay! Your provider now honours the pact it has with your consumer. You can now h
201
221
 
202
222
  ### Using provider states
203
223
 
204
- Having different service provider states allows you to test the same request with different expected responses.
224
+ Provider states allow different fixtures to be loaded on the provider to allow you to test the same request with different expected responses.
205
225
 
206
226
  For example, some code that creates the pact in a consumer project might look like this:
207
227
 
@@ -218,9 +238,19 @@ my_service.
218
238
  given("a thing does not exist").
219
239
  upon_receiving("a request for a thing").
220
240
  with(method: 'get', path: '/thing').
221
- will_respond_with(status: 404, :body => {error: "There is no thing :("} )
241
+ will_respond_with(status: 404)
242
+
243
+ ...
244
+
245
+ my_service.
246
+ given("an error occurs while retrieving a thing").
247
+ upon_receiving("a request for a thing").
248
+ with(method: 'get', path: '/thing').
249
+ will_respond_with(status: 500, :body => {message: "An error occurred"}, :headers => { 'Content-Type' => 'application/json'} )
222
250
  ```
223
251
 
252
+
253
+
224
254
  To define service provider states that create the right data for "a thing exists" and "a thing does not exist", write the following in the service provider project. (The consumer name here must match the name of the consumer configured in your consumer project for it to correctly find these provider states.)
225
255
 
226
256
 
@@ -241,6 +271,12 @@ Pact.provider_states_for 'My Service Consumer' do
241
271
  provider_state "a thing does not exist" do
242
272
  no_op # If there's nothing to do because the state name is more for documentation purposes, you can use no_op to imply this.
243
273
  end
274
+
275
+ provider_state "an error occurs while retrieving a thing" do
276
+ set_up do
277
+ ThingRepository.stub(:find).and_raise("An error occurred!")
278
+ end
279
+ end
244
280
  end
245
281
 
246
282
  ```
@@ -329,63 +365,24 @@ To execute a subset of the specs when running any of the pact verification tasks
329
365
 
330
366
  $ PACT_DESCRIPTION="a request for something" PACT_PROVIDER_STATE="something exists" rake pact:verify
331
367
 
332
- ### Running a standalone mock server
333
-
334
- A pact service can be run locally and is really useful for debugging purposes.
368
+ See [Frequently Asked Questions](https://github.com/realestate-com-au/pact/blob/master/documentation/faq.md) and [Rarely Asked Questions](https://github.com/realestate-com-au/pact/blob/master/documentation/raq.md) and [Terminology](https://github.com/realestate-com-au/pact/blob/master/documentation/terminology.md) for more information.
335
369
 
336
- $ bundle exec pact service -p <port-num>
337
370
 
338
- The service prints messages it recieves to stdout which can be really useful
339
- when diagnosing issues with pacts.
371
+ ## Related Gems
340
372
 
341
- ### To run your consumer app as a process during your consumer specs
373
+ [Pact Provider Proxy](https://github.com/bethesque/pact-provider-proxy) - Verify a pact against a running server, allowing you to use pacts with a provider of any language.
342
374
 
343
- Eg. for Capybara tests
375
+ [Pact Broker](https://github.com/bethesque/pact_broker) - A pact repository. Provides endpoints to access published pacts, meaning you don't need to use messy CI URLs in your codebase. Enables cross testing of prod/head versions of your consumer and provider, allowing you to determine whether the head version of one is compatible with the production version of the other. Helps you to answer that ever so important question, "can I deploy without breaking all the things?"
344
376
 
345
- ```ruby
346
- Pact.service_consumer "My Consumer" do
347
- app my_consumer_rack_app
348
- port 4321
349
- end
350
- ```
351
-
352
- ### Handling multiple headers with the same name
353
-
354
- RFC 2616 states that two headers with the same name can interpreted as a single header with two comma-separated values. This is the safest way to specify multiple headers with the same name, as Rack will only pass the last value through when they are defined separately (see https://github.com/rack/rack/issues/436).
355
-
356
- ```ruby
357
- my_service_provider.
358
- .given("it is RFC 2616 compliant")
359
- .upon_receiving("a request with a header with commas separated values")
360
- .with( method: :get, path: '/', headers: {'X-Request-Multival' => "A, B"} )
361
- .will_respond_with(
362
- status: 200, headers: {'X-Response-Multival' => "C, D"}
363
- )
364
-
365
- ```
366
-
367
- ### Pact file write mode
368
-
369
- 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.
370
-
371
- ### To use RSpec hooks for pact:verify
372
-
373
- The pact:verify RSpec examples have the metadata `{:pact => :verify}` defined. You can add RSpec hooks using a filter as shown here:
374
-
375
- ```ruby
376
- RSpec.configure do | config |
377
- config.before :each, :pact => :verify do
378
- # Your code here
379
- end
380
- end
381
- ```
377
+ [Pact Broker Client](https://github.com/bethesque/pact_broker-client) - Contains rake tasks for publishing pacts to the pact_broker.
382
378
 
383
- See https://www.relishapp.com/rspec/rspec-core/docs/hooks/filters for more information.
379
+ [Shokkenki](https://github.com/brentsnook/shokkenki) - Another Consumer Driven Contract gem written by one of Pact's original authors, Brent Snook.
384
380
 
385
381
  ## TODO
386
382
 
387
383
  Short term:
388
384
  - FIX EXAMPLE!!!
385
+ - Support hash of query params
389
386
 
390
387
  Long term:
391
388
  - 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/Rakefile CHANGED
@@ -1,22 +1,4 @@
1
- require 'bundler/gem_helper'
2
- module Bundler
3
- class GemHelper
4
- def install
5
- desc "Build #{name}-#{version}.gem into the pkg directory"
6
- task 'build' do
7
- build_gem
8
- end
9
-
10
- desc "Build and install #{name}-#{version}.gem into system gems"
11
- task 'install' do
12
- install_gem
13
- end
14
-
15
- GemHelper.instance = self
16
- end
17
- end
18
- end
19
- Bundler::GemHelper.install_tasks
1
+ require "bundler/gem_tasks"
20
2
  require 'rspec/core/rake_task'
21
3
 
22
4
  Dir.glob('lib/tasks/**/*.rake').each { |task| load task }
@@ -25,9 +7,3 @@ RSpec::Core::RakeTask.new(:spec)
25
7
 
26
8
  task :default => [:spec, :spec_with_active_support, 'pact:tests']
27
9
 
28
- desc "Release to REA gems host"
29
- task :publish => :build do
30
- gem_file = "pkg/pact-#{Pact::VERSION}.gem"
31
- require 'geminabox-client'
32
- Geminabox::Client.new('http://rea-rubygems').upload(gem_file)
33
- end
Binary file
@@ -0,0 +1,45 @@
1
+ # Frequently asked questions
2
+
3
+ ## How can I verify a pact against a non-ruby provider?
4
+
5
+ You can verify a pact against any running server, regardless of language, using [pact-provider-proxy](https://github.com/bethesque/pact-provider-proxy).
6
+
7
+ There is also a JVM version of pact under development. Have a look at [pact-jvm](https://github.com/DiUS/pact-jvm), the that contains the equivalent of pact/consumer and pact/provider.
8
+
9
+ ### How can I create a pact for a consumer that is not ruby or on the JVM?
10
+
11
+ Become famous, and write a pact-consumer library yourself! Then let us know about it so we can put a link to it in the documentation.
12
+
13
+ ### How can I specify hooks to be executed before/after all examples for pact:verify?
14
+
15
+ The pact:verify RSpec examples have the metadata `{:pact => :verify}` defined. You can add RSpec hooks using a filter as shown here:
16
+
17
+ ```ruby
18
+ RSpec.configure do | config |
19
+ config.before :each, :pact => :verify do
20
+ # Your code here
21
+ end
22
+ end
23
+ ```
24
+
25
+ See https://www.relishapp.com/rspec/rspec-core/docs/hooks/filters for more information.
26
+
27
+ ### How can I run my consumer UI during my consumer specs so I can execute the tests using a browser?
28
+
29
+ Eg. for Capybara tests
30
+
31
+ ```ruby
32
+ Pact.service_consumer "My Consumer" do
33
+ app <your rack app here>
34
+ port 4321
35
+ end
36
+ ```
37
+
38
+ ### Should the database or any other part of the provider be stubbed?
39
+
40
+ This is a hotly debated issue.
41
+
42
+ The pact authors' experience with using pacts to test microservices has been that using the set_up hooks to populate the database, and running pact:verify with all the real provider code has worked very well, and gives us full confidence that the end to end scenario will work in the deployed code.
43
+
44
+ However, if you have a large and complex provider, you might decide to stub some of your application code. If you do, remember to add your own "verification" of your stubbed methods - write another test that will break if the behaviour of the stubbed methods changes.
45
+
@@ -0,0 +1,39 @@
1
+ # Rarely asked questions
2
+
3
+ ### How can I run a standalone mock server?
4
+
5
+ By default, a mock service will be started automatically by the pact gem when running the consumer tests. A standalone mock service can be run locally and is useful for debugging purposes.
6
+
7
+ ```ruby
8
+ Pact.service_consumer "My Service Consumer" do
9
+ has_pact_with "My Service Provider" do
10
+ mock_service :my_service_provider do
11
+ port <port-num>
12
+ standalone true #Tell the pact gem not to automatically start the mock service
13
+ end
14
+ end
15
+ end
16
+ ```
17
+ $ bundle exec pact service -p <port-num>
18
+
19
+ The service prints messages it recieves to stdout which can be really useful
20
+ when diagnosing issues with pacts.
21
+
22
+ ### How can I specify multiple headers with the same name?
23
+
24
+ RFC 2616 states that two headers with the same name can interpreted as a single header with two comma-separated values. This is the safest way to specify multiple headers with the same name, as Rack will only pass the last value through when they are defined separately (see https://github.com/rack/rack/issues/436).
25
+
26
+ ```ruby
27
+ my_service_provider.
28
+ .given("it is RFC 2616 compliant")
29
+ .upon_receiving("a request with a header with commas separated values")
30
+ .with( method: :get, path: '/', headers: {'X-Request-Multival' => "A, B"} )
31
+ .will_respond_with(
32
+ status: 200, headers: {'X-Response-Multival' => "C, D"}
33
+ )
34
+
35
+ ```
36
+
37
+ ### What is this pact file write mode?
38
+
39
+ 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.
@@ -0,0 +1,25 @@
1
+ # Terminology
2
+
3
+ ### Service Consumer
4
+
5
+ A component that initiates a HTTP request to another component (the service provider). Note that this does not depend on the way the data flows - whether it is a GET or a PUT/POST/PATCH, the consumer is the initiator of the HTTP request.
6
+
7
+ ### Service Provider
8
+
9
+ A server that responds to an HTTP request from another component (the service consumer).
10
+
11
+ ### Mock Service Provider
12
+
13
+ Used by tests in the consumer project to mock out the actual service provider, meaning that integration-like tests can be run without requiring the actual service provider to be available.
14
+
15
+ ### Pact file
16
+
17
+ A file containing the JSON serialised requests and responses that were defined in the consumer tests.
18
+
19
+ ### Pact verification
20
+
21
+ To verify a pact, the requests contained in a pact file are replayed against the provider code, and the responses returned are checked to ensure they match those expected in the pact file.
22
+
23
+ ## Provider state
24
+
25
+ A name describing a "state" (like a fixture) that the provider should be in when a given request is replayed against it. Eg. "there is an alligator called Mary" or "there are no alligators". A provider state name is specified when writing the consumer specs, then, when the pact verification is set up in the provider, the same name will be used to identify the set up code block that should be run before the request is executed.
@@ -1,7 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'bundler', '~> 1.3.0'
4
-
5
3
  group :development, :test do
6
4
  gem 'rspec'
7
5
  gem 'pact', path: '../../'
@@ -10,5 +8,7 @@ end
10
8
 
11
9
  gem 'rake'
12
10
  gem 'rack', '~>1.5.2'
13
- gem 'json', '~>1.6.8'
14
- gem 'httparty'
11
+ gem 'json', '~>1.6'
12
+ gem 'sqlite3'
13
+ gem 'sequel'
14
+ gem 'sinatra'
@@ -1,39 +1,35 @@
1
1
  PATH
2
2
  remote: ../../
3
3
  specs:
4
- pact (1.0.9)
5
- awesome_print (~> 1.1.0)
4
+ pact (1.0.30)
5
+ awesome_print (~> 1.1)
6
6
  find_a_port (~> 1.0.1)
7
- hashie (~> 2.0)
8
7
  json
9
8
  rack-test (~> 0.6.2)
10
9
  randexp (~> 0.1.7)
11
10
  rspec (~> 2.12)
12
11
  thin
13
12
  thor
13
+ webrick
14
14
 
15
15
  GEM
16
16
  remote: https://rubygems.org/
17
17
  specs:
18
- awesome_print (1.1.0)
18
+ awesome_print (1.2.0)
19
19
  coderay (1.0.9)
20
20
  daemons (1.1.9)
21
21
  diff-lcs (1.2.4)
22
22
  eventmachine (1.0.3)
23
23
  find_a_port (1.0.1)
24
- hashie (2.0.5)
25
- httparty (0.11.0)
26
- multi_json (~> 1.0)
27
- multi_xml (>= 0.5.2)
28
24
  json (1.6.8)
29
25
  method_source (0.8.2)
30
- multi_json (1.8.0)
31
- multi_xml (0.5.5)
32
26
  pry (0.9.12.2)
33
27
  coderay (~> 1.0.5)
34
28
  method_source (~> 0.8)
35
29
  slop (~> 3.4)
36
30
  rack (1.5.2)
31
+ rack-protection (1.5.1)
32
+ rack
37
33
  rack-test (0.6.2)
38
34
  rack (>= 1.0)
39
35
  rake (10.1.0)
@@ -46,22 +42,31 @@ GEM
46
42
  rspec-expectations (2.14.2)
47
43
  diff-lcs (>= 1.1.3, < 2.0)
48
44
  rspec-mocks (2.14.3)
45
+ sequel (4.5.0)
46
+ sinatra (1.4.4)
47
+ rack (~> 1.4)
48
+ rack-protection (~> 1.4)
49
+ tilt (~> 1.3, >= 1.3.4)
49
50
  slop (3.4.6)
50
- thin (1.5.1)
51
+ sqlite3 (1.3.8)
52
+ thin (1.6.1)
51
53
  daemons (>= 1.0.9)
52
- eventmachine (>= 0.12.6)
54
+ eventmachine (>= 1.0.0)
53
55
  rack (>= 1.0.0)
54
56
  thor (0.18.1)
57
+ tilt (1.4.1)
58
+ webrick (1.3.1)
55
59
 
56
60
  PLATFORMS
57
61
  ruby
58
62
 
59
63
  DEPENDENCIES
60
- bundler (~> 1.3.0)
61
- httparty
62
- json (~> 1.6.8)
64
+ json (~> 1.6)
63
65
  pact!
64
66
  pry
65
67
  rack (~> 1.5.2)
66
68
  rake
67
69
  rspec
70
+ sequel
71
+ sinatra
72
+ sqlite3