Permalink
Browse files

Finish the allow_unused_http_interactions feature.

- Add cuke.
- Add #assert_no_unused_interactions! call from Cassette#eject.
- Rename error class to match option.
- Various other small fixes.
  • Loading branch information...
1 parent 75d64a7 commit d6e96104d5fe8c68eb1e348547a3aeefc92a5392 @myronmarston committed May 30, 2012
View
@@ -14,6 +14,7 @@
- update_content_length_header.feature
- decompress.feature
- persistence.feature
+ - allow_unused_http_interactions.feature
- record_modes:
- once.feature
- new_episodes.feature
@@ -0,0 +1,86 @@
+Feature: Allow Unused HTTP Interactions
+
+ If set to false, this cassette option will cause VCR to raise an error
+ when a cassette is ejected and there are unused HTTP interactions remaining.
+
+ It verifies that all requests included in the cassette were made, and allows
+ VCR to function a bit like a mock object at the HTTP layer.
+
+ The option defaults to true (mostly for backwards compatibility).
+
+ Background:
+ Given a file named "vcr_config.rb" with:
+ """ruby
+ require 'vcr'
+
+ VCR.configure do |c|
+ c.hook_into :fakeweb
+ c.cassette_library_dir = 'cassettes'
+ end
+ """
+ And a previously recorded cassette file "cassettes/example.yml" with:
+ """
+ ---
+ http_interactions:
+ - request:
+ method: get
+ uri: http://example.com/foo
+ body:
+ encoding: UTF-8
+ string: ""
+ headers: {}
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Content-Length:
+ - "5"
+ body:
+ encoding: UTF-8
+ string: Hello
+ http_version: "1.1"
+ recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
+ recorded_with: VCR 2.0.0
+ """
+
+ Scenario: Unused HTTP interactions are allowed by default
+ Given a file named "allowed_by_default.rb" with:
+ """ruby
+ require 'vcr_config'
+
+ VCR.use_cassette("example") do
+ # no requests
+ end
+ """
+ When I run `ruby allowed_by_default.rb`
+ Then it should pass
+
+ Scenario: Error raised if option is false and there are unused interactions
+ Given a file named "disallowed_with_no_requests.rb" with:
+ """ruby
+ require 'vcr_config'
+
+ VCR.use_cassette("example", :allow_unused_http_interactions => false) do
+ # no requests
+ end
+ """
+ When I run `ruby disallowed_with_no_requests.rb`
+ Then it should fail with:
+ """
+ There are unused HTTP interactions left in the cassette: (VCR::Errors::UnusedHTTPInteractionError)
+ - [get http://example.com/foo] => [200 "Hello"]
+ """
+
+ Scenario: No error raised if option is false and all interactions are used
+ Given a file named "disallowed_with_all_requests.rb" with:
+ """ruby
+ require 'vcr_config'
+
+ VCR.use_cassette("example", :allow_unused_http_interactions => false) do
+ Net::HTTP.get_response(URI("http://example.com/foo"))
+ end
+ """
+ When I run `ruby disallowed_with_all_requests.rb`
+ Then it should pass
+
@@ -30,7 +30,7 @@ Feature: Debug Logging
When I run `ruby debug_logger.rb record.log --with-server`
Then the file "record.log" should contain exactly:
"""
- [Cassette: 'example'] Initialized with options: {:record=>:once, :match_requests_on=>[:method, :uri], :serialize_with=>:yaml, :persist_with=>:file_system}
+ [Cassette: 'example'] Initialized with options: {:record=>:once, :match_requests_on=>[:method, :uri], :allow_unused_http_interactions=>true, :serialize_with=>:yaml, :persist_with=>:file_system}
[fakeweb] Handling request: [get http://localhost:7777/] (disabled: false)
[Cassette: 'example'] Initialized HTTPInteractionList with request matchers [:method, :uri] and 0 interaction(s): { }
[fakeweb] Identified request type (recordable) for [get http://localhost:7777/]
@@ -40,7 +40,7 @@ Feature: Debug Logging
When I run `ruby debug_logger.rb playback.log`
Then the file "playback.log" should contain exactly:
"""
- [Cassette: 'example'] Initialized with options: {:record=>:once, :match_requests_on=>[:method, :uri], :serialize_with=>:yaml, :persist_with=>:file_system}
+ [Cassette: 'example'] Initialized with options: {:record=>:once, :match_requests_on=>[:method, :uri], :allow_unused_http_interactions=>true, :serialize_with=>:yaml, :persist_with=>:file_system}
[fakeweb] Handling request: [get http://localhost:7777/] (disabled: false)
[Cassette: 'example'] Initialized HTTPInteractionList with request matchers [:method, :uri] and 1 interaction(s): { [get http://localhost:7777/] => [200 "Hello World"] }
[Cassette: 'example'] Checking if [get http://localhost:7777/] matches [get http://localhost:7777/] using [:method, :uri]
@@ -196,3 +196,7 @@ def redis
redis.get(key).should include(value_fragment)
end
+Then /^it should (pass|fail)$/ do |pass_fail|
+ assert_success(pass_fail == 'pass')
+end
+
View
@@ -81,10 +81,9 @@ def current_cassette
# @option options :allow_playback_repeats [Boolean] Whether or not to
# allow a single HTTP interaction to be played back multiple times.
# Defaults to false.
- # @options options :allow_unused_http_interactions [Boolean] Whether or not to
- # allow that certain recorded HTTP interactions are not played back
- # during the use of the cassette. Setting this to false requires that
- # all interactions will be played back at least once.
+ # @options options :allow_unused_http_interactions [Boolean] If set to
+ # false, an error will be raised if a cassette is ejected before all
+ # previously recorded HTTP interactions have been used.
# Defaults to true.
# @option options :exclusive [Boolean] Whether or not to use only this
# cassette and to completely ignore any cassettes in the cassettes stack.
View
@@ -58,6 +58,7 @@ def initialize(name, options = {})
# disk.
def eject
write_recorded_interactions_to_disk
+ http_interactions.assert_no_unused_interactions! unless @allow_unused_http_interactions
end
# @private
@@ -124,7 +125,7 @@ def assert_valid_options!
end
end
- def extract_options
+ def extract_options
[:erb, :match_requests_on, :re_record_interval,
:allow_playback_repeats, :allow_unused_http_interactions, :exclusive].each do |name|
instance_variable_set("@#{name}", @options[name])
@@ -55,10 +55,16 @@ def remaining_unused_interaction_count
end
# Checks if there are no unused interactions left.
- # @raise [VCR::Errors::SkippedHTTPRequestError] when not all interactions were played back
- # when allow_episode_skipping is off.
+ #
+ # @raise [VCR::Errors::UnusedHTTPInteractionError] if not all interactions were played back.
def assert_no_unused_interactions!
- raise Errors::SkippedHTTPRequestError if has_unused_interactions?
+ return unless has_unused_interactions?
+
+ descriptions = @interactions.map do |i|
+ " - #{request_summary(i.request)} => #{response_summary(i.response)}"
+ end.join("\n")
+
+ raise Errors::UnusedHTTPInteractionError, "There are unused HTTP interactions left in the cassette:\n#{descriptions}"
end
private
View
@@ -45,11 +45,11 @@ class NotSupportedError < Error; end
# @see VCR::Response#decompress
class UnknownContentEncodingError < Error; end
- # Error raised when you eject a cassette when not all HTTP
- # interactions were already played back.
+ # Error raised when you eject a cassette before all previously
+ # recorded HTTP interactions are played back.
# @note Only applicable when :allow_episode_skipping is false.
- # @see VCR::HTTPInteractionList#assert_finished!
- class SkippedHTTPRequestError < Error; end
+ # @see VCR::HTTPInteractionList#assert_no_unused_interactions!
+ class UnusedHTTPInteractionError < Error; end
# Error raised when an HTTP request is made that VCR is unable to handle.
# @note VCR will raise this to force you to do something about the
@@ -88,9 +88,9 @@ def interaction(body, request_values)
describe "#assert_no_unused_interactions?" do
it 'should raise a SkippedHTTPRequestError when there are unused interactions left' do
- expect { list.assert_no_unused_interactions! }.to raise_error Errors::SkippedHTTPRequestError
+ expect { list.assert_no_unused_interactions! }.to raise_error(Errors::UnusedHTTPInteractionError)
list.response_for(request_with(:method => :put))
- expect { list.assert_no_unused_interactions! }.to raise_error Errors::SkippedHTTPRequestError
+ expect { list.assert_no_unused_interactions! }.to raise_error(Errors::UnusedHTTPInteractionError)
end
it 'should raise nothing when there are no unused interactions left' do
View
@@ -394,6 +394,26 @@ def stub_old_interactions(interactions)
describe '#eject' do
let(:custom_persister) { stub("custom persister", :[] => nil) }
+ it 'asserts that there are no unused interactions if allow_unused_http_interactions is set to false' do
+ cassette = VCR.insert_cassette("foo", :allow_unused_http_interactions => false)
+
+ interaction_list = cassette.http_interactions
+ interaction_list.should respond_to(:assert_no_unused_interactions!).with(0).arguments
+ interaction_list.should_receive(:assert_no_unused_interactions!)
+
+ cassette.eject
+ end
+
+ it 'does not assert that there are no unused interactions if allow_unused_http_interactions is set to true' do
+ cassette = VCR.insert_cassette("foo", :allow_unused_http_interactions => true)
+
+ interaction_list = cassette.http_interactions
+ interaction_list.should respond_to(:assert_no_unused_interactions!)
+ interaction_list.should_not_receive(:assert_no_unused_interactions!)
+
+ cassette.eject
+ end
+
it 'stores the cassette content using the configured persister' do
VCR.configuration.cassette_library_dir = nil
VCR.cassette_persisters[:foo] = custom_persister

0 comments on commit d6e9610

Please sign in to comment.