vcr 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +12 -0
- data/FullBuildRakeFile +22 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +46 -25
- data/Guardfile +9 -0
- data/README.md +10 -371
- data/Rakefile +6 -2
- data/TODO.md +4 -0
- data/features/support/env.rb +5 -1
- data/full_build +1 -0
- data/lib/vcr.rb +17 -7
- data/lib/vcr/basic_object.rb +39 -0
- data/lib/vcr/config.rb +4 -7
- data/lib/vcr/deprecations.rb +14 -0
- data/lib/vcr/http_stubbing_adapters/common.rb +44 -13
- data/lib/vcr/http_stubbing_adapters/fakeweb.rb +17 -28
- data/lib/vcr/http_stubbing_adapters/multi_object_proxy.rb +43 -0
- data/lib/vcr/http_stubbing_adapters/typhoeus.rb +101 -0
- data/lib/vcr/http_stubbing_adapters/webmock.rb +16 -37
- data/lib/vcr/internet_connection.rb +2 -1
- data/lib/vcr/structs.rb +32 -0
- data/lib/vcr/version.rb +1 -1
- data/spec/config_spec.rb +5 -25
- data/spec/deprecations_spec.rb +31 -3
- data/spec/extensions/net_http_spec.rb +1 -0
- data/spec/fixtures/1.9.1/fake_example.com_responses.yml +32 -1
- data/spec/fixtures/not_1.9.1/fake_example.com_responses.yml +32 -1
- data/spec/http_stubbing_adapters/fakeweb_spec.rb +9 -24
- data/spec/http_stubbing_adapters/multi_object_proxy_spec.rb +101 -0
- data/spec/http_stubbing_adapters/typhoeus_spec.rb +28 -0
- data/spec/http_stubbing_adapters/webmock_spec.rb +8 -26
- data/spec/internet_connection_spec.rb +25 -7
- data/spec/spec_helper.rb +3 -1
- data/spec/structs_spec.rb +30 -6
- data/spec/support/http_library_adapters.rb +50 -15
- data/spec/support/http_stubbing_adapter.rb +65 -56
- data/spec/support/version_checker.rb +29 -0
- data/spec/vcr_spec.rb +30 -12
- data/vcr.gemspec +5 -4
- metadata +44 -15
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.3.0 (November 11, 2010)
|
4
|
+
|
5
|
+
[Full Changelog](http://github.com/myronmarston/vcr/compare/v1.2.0...v.1.3.0)
|
6
|
+
|
7
|
+
* Moved documentation from README to [Wiki](http://github.com/myronmarston/vcr/wiki).
|
8
|
+
* Refactoring and code cleanup.
|
9
|
+
* Fix InternetConnection.available? so that it memoizes correctly when a connection is not available.
|
10
|
+
* Fix WebMock version checking to allow newly released 1.5.0 to be used without a warning.
|
11
|
+
* Add support for [Typhoeus](https://github.com/pauldix/typhoeus). Thanks to
|
12
|
+
[David Balatero](https://github.com/dbalatero) for making the necessary changes in Typhoeus
|
13
|
+
to support VCR.
|
14
|
+
|
3
15
|
## 1.2.0 (October 13, 2010)
|
4
16
|
|
5
17
|
[Full Changelog](http://github.com/myronmarston/vcr/compare/v1.1.2...v1.2.0)
|
data/FullBuildRakeFile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# this is in a separate rakefile because our main one depends on the bundled gems
|
2
|
+
# already being installed. This must be able to run w/o bundled gems installed.
|
3
|
+
|
4
|
+
desc "Run a full build: install necessary gems with bundler, runs specs, run cukes"
|
5
|
+
task :build => :ensure_bundler_installed do
|
6
|
+
sh "bundle install"
|
7
|
+
sh "rake"
|
8
|
+
end
|
9
|
+
|
10
|
+
task :ensure_bundler_installed do
|
11
|
+
installed = begin
|
12
|
+
require 'rubygems'
|
13
|
+
require 'bundler'
|
14
|
+
true
|
15
|
+
rescue LoadError
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
unless installed
|
20
|
+
sh "gem install bundler"
|
21
|
+
end
|
22
|
+
end
|
data/Gemfile
CHANGED
@@ -7,13 +7,21 @@ group :development do
|
|
7
7
|
gem 'patron', '~> 0.4.6'
|
8
8
|
gem 'em-http-request', '~> 0.2.7'
|
9
9
|
gem 'curb', '~> 0.7.8'
|
10
|
+
gem 'typhoeus', '~> 0.2.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
platforms :jruby do
|
14
|
+
gem 'jruby-openssl'
|
10
15
|
end
|
11
16
|
end
|
12
17
|
|
13
18
|
# Additional gems that are useful, but not required for development.
|
14
19
|
group :extras do
|
20
|
+
gem 'guard-rspec'
|
21
|
+
|
15
22
|
platforms :mri do
|
16
23
|
gem 'rcov'
|
24
|
+
gem 'rb-fsevent'
|
17
25
|
end
|
18
26
|
|
19
27
|
platforms :mri_18 do
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
vcr (1.
|
4
|
+
vcr (1.3.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
@@ -9,15 +9,17 @@ GEM
|
|
9
9
|
addressable (2.2.2)
|
10
10
|
archive-tar-minitar (0.5.2)
|
11
11
|
aruba (0.2.1)
|
12
|
+
bouncy-castle-java (1.5.0145.2)
|
12
13
|
builder (2.1.2)
|
13
14
|
columnize (0.3.1)
|
15
|
+
configuration (1.1.0)
|
14
16
|
crack (0.1.8)
|
15
|
-
cucumber (0.
|
17
|
+
cucumber (0.9.4)
|
16
18
|
builder (~> 2.1.2)
|
17
19
|
diff-lcs (~> 1.1.2)
|
18
|
-
gherkin (~> 2.
|
19
|
-
|
20
|
-
term-ansicolor (~> 1.0.
|
20
|
+
gherkin (~> 2.2.9)
|
21
|
+
json (~> 1.4.6)
|
22
|
+
term-ansicolor (~> 1.0.5)
|
21
23
|
curb (0.7.8)
|
22
24
|
diff-lcs (1.1.2)
|
23
25
|
em-http-request (0.2.12)
|
@@ -25,29 +27,43 @@ GEM
|
|
25
27
|
eventmachine (>= 0.12.9)
|
26
28
|
eventmachine (0.12.10)
|
27
29
|
fakeweb (1.3.0)
|
28
|
-
gherkin (2.
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
gherkin (2.2.9)
|
31
|
+
json (~> 1.4.6)
|
32
|
+
term-ansicolor (~> 1.0.5)
|
33
|
+
gherkin (2.2.9-java)
|
34
|
+
json (~> 1.4.6)
|
35
|
+
term-ansicolor (~> 1.0.5)
|
36
|
+
guard (0.2.2)
|
37
|
+
open_gem (~> 1.4.2)
|
38
|
+
thor (~> 0.14.3)
|
39
|
+
guard-rspec (0.1.5)
|
40
|
+
guard (>= 0.2.0)
|
32
41
|
httpclient (2.1.5.2)
|
33
|
-
|
42
|
+
jruby-openssl (0.7.2)
|
43
|
+
bouncy-castle-java
|
44
|
+
json (1.4.6)
|
45
|
+
json (1.4.6-java)
|
46
|
+
launchy (0.3.7)
|
47
|
+
configuration (>= 0.0.5)
|
48
|
+
rake (>= 0.8.1)
|
34
49
|
linecache (0.43)
|
35
50
|
linecache19 (0.5.11)
|
36
51
|
ruby_core_source (>= 0.1.4)
|
52
|
+
open_gem (1.4.2)
|
53
|
+
launchy (~> 0.3.5)
|
37
54
|
patron (0.4.9)
|
38
55
|
rack (1.1.0)
|
39
56
|
rake (0.8.7)
|
57
|
+
rb-fsevent (0.3.6)
|
40
58
|
rcov (0.9.9)
|
41
|
-
rspec (2.
|
42
|
-
rspec-core (
|
43
|
-
rspec-expectations (
|
44
|
-
rspec-mocks (
|
45
|
-
rspec-core (2.
|
46
|
-
rspec-expectations (2.
|
47
|
-
diff-lcs (
|
48
|
-
rspec-mocks (2.
|
49
|
-
rspec-core (= 2.0.0)
|
50
|
-
rspec-expectations (= 2.0.0)
|
59
|
+
rspec (2.1.0)
|
60
|
+
rspec-core (~> 2.1.0)
|
61
|
+
rspec-expectations (~> 2.1.0)
|
62
|
+
rspec-mocks (~> 2.1.0)
|
63
|
+
rspec-core (2.1.0)
|
64
|
+
rspec-expectations (2.1.0)
|
65
|
+
diff-lcs (~> 1.1.2)
|
66
|
+
rspec-mocks (2.1.0)
|
51
67
|
ruby-debug (0.10.3)
|
52
68
|
columnize (>= 0.1)
|
53
69
|
ruby-debug-base (~> 0.10.3.0)
|
@@ -64,9 +80,10 @@ GEM
|
|
64
80
|
ruby_core_source (0.1.4)
|
65
81
|
archive-tar-minitar (>= 0.5.2)
|
66
82
|
term-ansicolor (1.0.5)
|
83
|
+
thor (0.14.4)
|
67
84
|
timecop (0.3.5)
|
68
|
-
|
69
|
-
webmock (1.
|
85
|
+
typhoeus (0.2.0)
|
86
|
+
webmock (1.5.0)
|
70
87
|
addressable (>= 2.2.2)
|
71
88
|
crack (>= 0.1.7)
|
72
89
|
|
@@ -77,19 +94,23 @@ PLATFORMS
|
|
77
94
|
DEPENDENCIES
|
78
95
|
aruba (~> 0.2.1)
|
79
96
|
bundler (~> 1.0.0)
|
80
|
-
cucumber (~> 0.
|
97
|
+
cucumber (~> 0.9.4)
|
81
98
|
curb (~> 0.7.8)
|
82
99
|
em-http-request (~> 0.2.7)
|
83
100
|
fakeweb (~> 1.3.0)
|
101
|
+
guard-rspec
|
84
102
|
httpclient (~> 2.1.5.2)
|
103
|
+
jruby-openssl
|
85
104
|
patron (~> 0.4.6)
|
86
105
|
rack (= 1.1.0)
|
87
106
|
rake (~> 0.8.7)
|
107
|
+
rb-fsevent
|
88
108
|
rcov
|
89
|
-
rspec (~> 2.
|
109
|
+
rspec (~> 2.1.0)
|
90
110
|
ruby-debug
|
91
111
|
ruby-debug-base19 (= 0.11.23)
|
92
112
|
ruby-debug19
|
93
113
|
timecop (~> 0.3.5)
|
114
|
+
typhoeus (~> 0.2.0)
|
94
115
|
vcr!
|
95
|
-
webmock (
|
116
|
+
webmock (>= 1.5.0)
|
data/Guardfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at http://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2 do
|
5
|
+
watch('^spec/(.*)_spec.rb')
|
6
|
+
watch('^lib/vcr.rb') { "spec/vcr_spec.rb" }
|
7
|
+
watch('^lib/vcr/(.*)\.rb') { |m| "spec/#{m[1]}_spec.rb" }
|
8
|
+
watch('^spec/spec_helper.rb') { "spec" }
|
9
|
+
end
|
data/README.md
CHANGED
@@ -2,18 +2,6 @@
|
|
2
2
|
|
3
3
|
Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.
|
4
4
|
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
gem install vcr
|
8
|
-
|
9
|
-
You'll also need either [FakeWeb](http://github.com/chrisk/fakeweb) or [WebMock](http://github.com/bblimke/webmock):
|
10
|
-
|
11
|
-
gem install fakeweb
|
12
|
-
|
13
|
-
or
|
14
|
-
|
15
|
-
gem install webmock
|
16
|
-
|
17
5
|
## Synopsis
|
18
6
|
|
19
7
|
require 'test/unit'
|
@@ -21,7 +9,7 @@ or
|
|
21
9
|
|
22
10
|
VCR.config do |c|
|
23
11
|
c.cassette_library_dir = 'fixtures/vcr_cassettes'
|
24
|
-
c.
|
12
|
+
c.stub_with :webmock # or :fakeweb
|
25
13
|
end
|
26
14
|
|
27
15
|
class VCRTest < Test::Unit::TestCase
|
@@ -49,6 +37,7 @@ maintenance) and accurate (the response from example.com will contain the same h
|
|
49
37
|
* [HTTPClient](http://github.com/nahi/httpclient) (WebMock)
|
50
38
|
* [em-http-request](http://github.com/igrigorik/em-http-request) (WebMock)
|
51
39
|
* [Net::HTTP](http://www.ruby-doc.org/stdlib/libdoc/net/http/rdoc/index.html) (FakeWeb and WebMock)
|
40
|
+
* [Typhoeus](https://github.com/pauldix/typhoeus)
|
52
41
|
* And of course any library built on Net::HTTP, such as [Mechanize](http://github.com/tenderlove/mechanize),
|
53
42
|
[HTTParty](http://github.com/jnunemaker/httparty) or [Rest Client](http://github.com/archiloque/rest-client).
|
54
43
|
* Request matching is configurable based on HTTP method, URI, host, path, body and headers.
|
@@ -59,9 +48,13 @@ maintenance) and accurate (the response from example.com will contain the same h
|
|
59
48
|
* Disables all HTTP requests that you don't explicitly allow.
|
60
49
|
* Simple cucumber integration is provided using tags.
|
61
50
|
* Known to work well with many popular ruby libraries including RSpec 1 & 2, Cucumber, Test::Unit,
|
62
|
-
Capybara, Mechanize
|
51
|
+
Capybara, Mechanize, Rest-Client and HTTParty.
|
63
52
|
* Extensively tested on 7 different ruby interpretters.
|
64
53
|
|
54
|
+
## Usage
|
55
|
+
|
56
|
+
Visit the [wiki](http://github.com/myronmarston/vcr/wiki) for usage info and documentation.
|
57
|
+
|
65
58
|
## Development
|
66
59
|
|
67
60
|
* Source hosted on [GitHub](http://github.com/myronmarston/vcr).
|
@@ -70,352 +63,7 @@ maintenance) and accurate (the response from example.com will contain the same h
|
|
70
63
|
* Pull requests are very welcome! Please include spec and/or feature coverage for every patch,
|
71
64
|
and create a topic branch for every separate change you make.
|
72
65
|
|
73
|
-
|
74
|
-
|
75
|
-
Cassettes are the medium to which VCR records HTTP interactions, and the medium from which it replays them.
|
76
|
-
While a cassette is in use, new HTTP requests (or "new episodes", as VCR calls them) either get
|
77
|
-
recorded, or an error will be raised, depending on the cassette's `:record` mode (see below). When you use
|
78
|
-
a cassette that contains previously recorded HTTP interactions, it registers them with the http stubbing
|
79
|
-
library of your choice (fakeweb or webmock) so that HTTP requests get the recorded response. Between test
|
80
|
-
runs, cassettes are stored on disk as YAML files in your configured cassette library directory.
|
81
|
-
|
82
|
-
Each cassette acts a bit like a sandbox: it has an effect on HTTP requests during the current test while it
|
83
|
-
is inserted, but has no effect on the rest of your test suite.
|
84
|
-
|
85
|
-
Cassettes can be configured with a few options:
|
86
|
-
|
87
|
-
* `:record`: Specifies a record mode for this cassette.
|
88
|
-
* `:erb`: Used for dynamic cassettes (see below for more details).
|
89
|
-
* `:match_requests_on`: An array of request attributes to match on (see below for more details).
|
90
|
-
* `:re_record_interval`: Controls automatic re-recording of the cassette (see below for more details).
|
91
|
-
|
92
|
-
## Record modes
|
93
|
-
|
94
|
-
VCR supports 3 record modes. You can set a default record mode in your configuration (see below)
|
95
|
-
and a per-cassette record mode when inserting a cassette. The record modes are:
|
96
|
-
|
97
|
-
* `:new_episodes`: Previously recorded HTTP interactions will be replayed. New HTTP interactions will be recorded.
|
98
|
-
This is generally the most useful mode. VCR will automatically record and replay new HTTP requests as your
|
99
|
-
codebase evolves to make new requests.
|
100
|
-
* `:all`: Previously recorded HTTP interactions will be ignored. All HTTP interactions will be recorded.
|
101
|
-
This is useful if you're interested in using VCR to log your HTTP interactions but don't care to ever replay
|
102
|
-
them. Alternately, you can temporarily change your record mode to `:all` to force it to re-record all requests.
|
103
|
-
* `:none`: Previously recorded HTTP interactions will be replayed. New HTTP interactions will result in an error.
|
104
|
-
This mode is useful when your code makes potentially dangerous HTTP requests (i.e. it hits a production
|
105
|
-
server rather than a sandbox/staging server), as it will prevent any new requests from completing, raising
|
106
|
-
an error instead. Generally, you will temporarily use the `:new_episodes` or `:all` record modes
|
107
|
-
to perform the initial recording before changing it to `:none`.
|
108
|
-
|
109
|
-
When no cassette is inserted, all HTTP requests will result in a `Real HTTP connections are disabled` error.
|
110
|
-
|
111
|
-
## Request Matching
|
112
|
-
|
113
|
-
In order to properly replay previously recorded requests, VCR must match new HTTP requests to a previously
|
114
|
-
recorded one. By default, it matches on HTTP method and URI, since that is usually deterministic and
|
115
|
-
fully identifies the resource and action for typical RESTful APIs. In some cases (such as SOAP webservices)
|
116
|
-
this may not work so well, and VCR allows you to customize how requests are matched.
|
117
|
-
|
118
|
-
Cassettes take a `:match_requests_on` option that expects an array of request attributes to match on.
|
119
|
-
Supported attributes are:
|
120
|
-
|
121
|
-
* `:method`: The HTTP method (i.e. GET, POST, PUT or DELETE) of the request.
|
122
|
-
* `:uri`: The full URI of the request.
|
123
|
-
* `:host`: The host of the URI. You can use this (alone, or in combination with `:path`) as an alternative
|
124
|
-
to `:uri` to cause VCR to match using a regex that matches the host.
|
125
|
-
* `:path`: The path of the URI. You can use this (alone, or in combination with `:host`) as an alternative
|
126
|
-
to `:uri` to cause VCR to match using a regex that matches the path.
|
127
|
-
* `:body`: The body of the request.
|
128
|
-
* `:headers`: The request headers.
|
129
|
-
|
130
|
-
By default, VCR uses a `:match_requests_on` option like:
|
131
|
-
|
132
|
-
:match_requests_on => [:uri, :method]
|
133
|
-
|
134
|
-
If you want to match on another attribute, just add it to the array:
|
135
|
-
|
136
|
-
:match_requests_on => [:uri, :method, :body]
|
137
|
-
|
138
|
-
Note that FakeWeb cannot match on `:body` or `:headers`. In general, it is recommended that you configure
|
139
|
-
your cassettes to match on the most specific set of attributes that is deterministic.
|
140
|
-
|
141
|
-
## Configuration
|
142
|
-
|
143
|
-
require 'vcr'
|
144
|
-
|
145
|
-
VCR.config do |c|
|
146
|
-
c.cassette_library_dir = 'fixtures/cassette_library'
|
147
|
-
c.http_stubbing_library = :fakeweb
|
148
|
-
c.ignore_localhost = true
|
149
|
-
c.default_cassette_options = { :record => :none }
|
150
|
-
end
|
151
|
-
|
152
|
-
This can go pretty much wherever, as long as this code is run before your tests, specs or scenarios. I tend
|
153
|
-
to put it in `spec/support/vcr.rb`, `test/support/vcr.rb` or `features/support/vcr.rb`. You can set the following
|
154
|
-
configuration options:
|
155
|
-
|
156
|
-
* `cassette_library_dir`: VCR will save the cassette YAML files to this directory. If you are using Rails 3 and
|
157
|
-
ActiveRecord YAML fixtures, you will probably want to avoid putting VCR cassettes in a sub-directory of
|
158
|
-
`RAILS_ROOT/test/fixtures`. Rails will assume your cassette YAML files are ActiveRecord fixtures and raise an
|
159
|
-
error when the content doesn't conform to its expectations.
|
160
|
-
* `http_stubbing_library`: Which http stubbing library to use. Currently `:fakeweb` and `:webmock` are supported.
|
161
|
-
VCR will automatically configure FakeWeb/WebMock for you; you do not need to reference either one at all.
|
162
|
-
* `ignore_localhost`: Defaults to false. Setting it true does the following:
|
163
|
-
* Localhost requests will proceed as normal. The "Real HTTP connections are disabled" error will not occur.
|
164
|
-
* Localhost requests will not be recorded.
|
165
|
-
* Previously recorded localhost requests will not be replayed.
|
166
|
-
* `default_cassette_options`: The default options for your cassettes. These will be overridden by any options you
|
167
|
-
set on each individual cassette.
|
168
|
-
|
169
|
-
## Usage with your favorite ruby test/spec framework
|
170
|
-
|
171
|
-
VCR can easily be used with any ruby test or spec framework. Usually, you'll want to use `VCR.use_cassette`:
|
172
|
-
|
173
|
-
VCR.use_cassette('geocoding/Seattle, WA', :record => :new_episodes) do
|
174
|
-
# do something that makes an HTTP request
|
175
|
-
end
|
176
|
-
|
177
|
-
Alternately, with a framework like [shoulda](http://github.com/thoughtbot/shoulda), you can insert and eject a
|
178
|
-
cassette with individual method calls from setup and teardown:
|
179
|
-
|
180
|
-
context "Some object that makes an HTTP request" do
|
181
|
-
setup do
|
182
|
-
VCR.insert_cassette('geocoding/Seattle, WA', :record => :new_episodes)
|
183
|
-
end
|
184
|
-
|
185
|
-
should "make an HTTP request" do
|
186
|
-
# ...
|
187
|
-
end
|
188
|
-
|
189
|
-
should "make another HTTP request" do
|
190
|
-
# ...
|
191
|
-
end
|
192
|
-
|
193
|
-
teardown do
|
194
|
-
VCR.eject_cassette
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
## Usage with RSpec
|
199
|
-
|
200
|
-
If you're using RSpec, you can use a special macro provided by VCR:
|
201
|
-
|
202
|
-
describe MyApiClient do
|
203
|
-
context "create" do
|
204
|
-
# Pass use_vcr_cassette the same args you would pass VCR.use_cassette.
|
205
|
-
use_vcr_cassette "my_api_client/create", :record => :new_episodes
|
206
|
-
|
207
|
-
it "makes an HTTP request"
|
208
|
-
it "makes another HTTP request"
|
209
|
-
end
|
210
|
-
|
211
|
-
context "destroy" do
|
212
|
-
# You can leave off the cassette name and it will be inferred from the example group
|
213
|
-
# descriptions--in this case "MyApiClient/destroy".
|
214
|
-
# You can also leave off the options hash--the configured default options will be used.
|
215
|
-
use_vcr_cassette :record => :new_episodes, :match_requests_on => [:uri, :method, :body]
|
216
|
-
|
217
|
-
it "makes an HTTP request"
|
218
|
-
it "makes another HTTP request"
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
To use this, you need to configure RSpec to make the `use_vcr_cassette` available as a macro.
|
223
|
-
Here's how to do that for RSpec 1:
|
224
|
-
|
225
|
-
require 'vcr'
|
226
|
-
|
227
|
-
Spec::Runner.configure do |c|
|
228
|
-
c.extend VCR::RSpec::Macros
|
229
|
-
end
|
230
|
-
|
231
|
-
Or for RSpec 2:
|
232
|
-
|
233
|
-
require 'vcr'
|
234
|
-
|
235
|
-
RSpec.configure do |c|
|
236
|
-
c.extend VCR::RSpec::Macros
|
237
|
-
end
|
238
|
-
|
239
|
-
## Usage with Cucumber
|
240
|
-
|
241
|
-
VCR provides additional support for cucumber. You can of course use `VCR.use_cassette` within a step definition,
|
242
|
-
and that's the recommended way for any of your custom step definitions. But many times I find myself using generic
|
243
|
-
step definitions provided by another library (such as the webrat/capybara web steps generated by cucumber-rails),
|
244
|
-
and you don't want to modify these. VCR provides cucumber tagging support to help in these cases.
|
245
|
-
|
246
|
-
First, tag your scenario with something descriptive:
|
247
|
-
|
248
|
-
@facebook_http_request
|
249
|
-
Scenario: Sign up with facebook connect
|
250
|
-
|
251
|
-
Then let VCR know about this tag, in `features/support/vcr.rb` (or some similar support file):
|
252
|
-
|
253
|
-
VCR.cucumber_tags do |t|
|
254
|
-
t.tags '@facebook_http_request', '@twitter_status_update', :record => :none
|
255
|
-
t.tags '@another_scenario_tag'
|
256
|
-
end
|
257
|
-
|
258
|
-
For each of the tags you specify in your `cucumber_tags` block, VCR will set up an appropriate
|
259
|
-
[After hook](http://wiki.github.com/aslakhellesoy/cucumber/hooks) to use a cassette
|
260
|
-
for the entire scenario. The tag (minus the '@') will be used as the cassette name, and it'll
|
261
|
-
go in the `cucumber_tags` subdirectory of the configured cassette library directory.
|
262
|
-
|
263
|
-
If the last argument to `#tags` is a hash, VCR will use it as the options for the named cassettes.
|
264
|
-
|
265
|
-
## Usage with Capybara
|
266
|
-
|
267
|
-
When you use any of the javascript-enabled drivers (selenium, celerity, culerity) with
|
268
|
-
[capybara](http://github.com/jnicklas/capybara), it'll need to ping the app running on localhost.
|
269
|
-
Set the `ignore_localhost` option to true to allow this.
|
270
|
-
|
271
|
-
## Cassette Customization
|
272
|
-
|
273
|
-
Cassettes are stored as simple plain text YAML files and can easily be edited to suit your needs. One common need
|
274
|
-
is for a particular request to be stubbed using a regex rather than the raw URL. This is handy for URLs that contain
|
275
|
-
non-deterministic portions (such as timestamps)--since the URL will be a bit different each time, the URL from the
|
276
|
-
recorded request will not match the URL for future requests. You can simply change the URL to the YAML of the
|
277
|
-
appropriate regex.
|
278
|
-
|
279
|
-
Figure out the yaml in irb:
|
280
|
-
|
281
|
-
>> require 'yaml'
|
282
|
-
=> true
|
283
|
-
>> puts /example\.com\/\d+/.to_yaml
|
284
|
-
--- !ruby/regexp /example\.com\/\d+/
|
285
|
-
|
286
|
-
Edit your cassette file:
|
287
|
-
|
288
|
-
request: !ruby/struct:VCR::Request
|
289
|
-
method: :get
|
290
|
-
uri: !ruby/regexp /example\.com\/\d+/
|
291
|
-
body:
|
292
|
-
headers:
|
293
|
-
|
294
|
-
Note that it may be simpler (and better!) to use the `:match_requests_on` cassette option with `:host` and/or `:path`,
|
295
|
-
as that gives you a a URL regex without the need to manually edit the cassette file. If you do change a url to a regex
|
296
|
-
in a cassette file, VCR will use it, regardless of the `:match_requests_on` setting.
|
297
|
-
|
298
|
-
## Dynamic Cassettes
|
299
|
-
|
300
|
-
VCR's default recording and replaying is static. The exact response that is initially recorded will
|
301
|
-
be replayed for all future requests. Usually this is fine, but in some cases you need something more
|
302
|
-
dynamic. You can use [ERB](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/) for this.
|
303
|
-
|
304
|
-
Enable ERB evaluation of a cassette using the `:erb` option:
|
305
|
-
|
306
|
-
VCR.use_cassette('user-subscription', :erb => true) do
|
307
|
-
# do something that makes an HTTP request
|
308
|
-
end
|
309
|
-
|
310
|
-
You can use variables in your cassette's ERB by passing a hash:
|
311
|
-
|
312
|
-
VCR.use_cassette('user-subscription', :erb => { :user => User.last }) do
|
313
|
-
# do something that makes an HTTP request
|
314
|
-
end
|
315
|
-
|
316
|
-
In your cassette:
|
317
|
-
|
318
|
-
request: !ruby/struct:VCR::Request
|
319
|
-
method: :get
|
320
|
-
uri: http://some-domain.com:80/users/<%= user.id %>
|
321
|
-
body:
|
322
|
-
headers:
|
323
|
-
...
|
324
|
-
response: !ruby/struct:VCR::Response
|
325
|
-
...
|
326
|
-
body: Hello, <%= user.name %>!
|
327
|
-
|
328
|
-
## Automatic cassette re-recording
|
329
|
-
|
330
|
-
Over time, your cassettes may get out-of-date. APIs change and sites you scrape get updated. VCR provides
|
331
|
-
a facility to automatically re-record your cassettes. You enable re-recording using the
|
332
|
-
`:re_record_interval` option:
|
333
|
-
|
334
|
-
A_WEEK = 7 * 24 * 60 * 60 # or use 7.days if you're using ActiveSupport
|
335
|
-
|
336
|
-
VCR.use_cassette('my_cassette', :re_record_interval => A_WEEK) { ... }
|
337
|
-
|
338
|
-
If the cassette file was last modified more than 7 days ago, VCR will use the `:all` record mode (regardless
|
339
|
-
of the configured record mode) to allow new HTTP requests and record them. VCR will check to make sure you
|
340
|
-
have an internet connection before doing this, so if you are running the tests without one, the automatic
|
341
|
-
re-recording will not kick in.
|
342
|
-
|
343
|
-
## FakeWeb or WebMock?
|
344
|
-
|
345
|
-
VCR works fine with either FakeWeb or WebMock. Overall, WebMock has more features, and you'll need to use
|
346
|
-
WebMock if you want to use VCR with an HTTP library besides Net::HTTP. However, FakeWeb is currently
|
347
|
-
about three times faster than WebMock, so you may want to stick with FakeWeb if you don't need WebMock's
|
348
|
-
additional features. You can see the
|
349
|
-
[benchmarks](http://github.com/myronmarston/vcr/blob/master/benchmarks/http_stubbing_libraries.rb) for
|
350
|
-
more details.
|
351
|
-
|
352
|
-
You should not need to directly interact with either FakeWeb or WebMock. VCR will take care of disallowing
|
353
|
-
http connections when no cassette is inserted, and it will clean up all stubs/registrations when a cassette
|
354
|
-
is ejected. If you ever decide to switch HTTP stubbing libraries, you'll just have to update the VCR config
|
355
|
-
setting.
|
356
|
-
|
357
|
-
## Suggested Workflow
|
358
|
-
|
359
|
-
First, configure VCR as I have above. I like setting the default record mode to `:none`
|
360
|
-
so that no new HTTP requests are made without me explicitly allowing it, but if you may prefer to
|
361
|
-
set it to `:new_episodes`.
|
362
|
-
|
363
|
-
When an HTTP request is made, you'll get an error such as:
|
364
|
-
|
365
|
-
Real HTTP connections are disabled. Unregistered request: get http://example.com
|
366
|
-
|
367
|
-
Find the place that is making the HTTP request (the backtrace should help here). If you've already recorded this HTTP
|
368
|
-
request to a cassette from a different test, you can simply re-use the cassette. Use `VCR.use_cassette`, as
|
369
|
-
shown above. You may also want to refactor this into a helper method that sets up the VCR cassette and does whatever
|
370
|
-
makes the HTTP request:
|
371
|
-
|
372
|
-
def set_user_address(user, address, city, state)
|
373
|
-
VCR.use_cassette("geocoding/#{address}, #{city}, #{state}", :record => :new_episodes) do
|
374
|
-
user.address.update_attributes!(:address => address, :city => city, :state => state)
|
375
|
-
end
|
376
|
-
end
|
377
|
-
|
378
|
-
In this case, I've used a dynamic cassette name based on the address being geocoded. That way, each separate address
|
379
|
-
gets a different cassette, and tests that set the same user address will reuse the same cassette. I've also set
|
380
|
-
the record mode to `:new_episodes` so that VCR will automatically record geocoding requests for a new address
|
381
|
-
to a new cassette, without me having to change any code.
|
382
|
-
|
383
|
-
If the HTTP request that triggered the error is new, you'll have to record it for the first time. Simply use
|
384
|
-
`VCR.use_cassette` with the record mode set to `:new_episodes` or `:all`. Run the test again, and VCR will
|
385
|
-
record the HTTP interaction. I usually remove the record mode at this point so that it uses the default
|
386
|
-
of `:none` in the future. Future test runs will get the recorded response, and if your code changes so
|
387
|
-
that it is making a new HTTP request, you'll be notified by an error as shown above.
|
388
|
-
|
389
|
-
VCR is designed to be used very granularly. Rather than inserting a global cassette, I recommend you wrap individual
|
390
|
-
blocks of code in `VCR.use_cassette` and record logically grouped sets of requests.
|
391
|
-
|
392
|
-
## Ruby Interpreter Compatibility
|
393
|
-
|
394
|
-
VCR has been tested on the following ruby interpreters:
|
395
|
-
|
396
|
-
* MRI 1.8.6-p399
|
397
|
-
* MRI 1.8.7-p302
|
398
|
-
* MRI 1.9.1-p378
|
399
|
-
* MRI 1.9.2-p0
|
400
|
-
* REE 1.8.7-2010.02
|
401
|
-
* JRuby 1.5.1
|
402
|
-
* Rubinius 1.1
|
403
|
-
|
404
|
-
## Notes, etc.
|
405
|
-
|
406
|
-
* The objects serialized to the cassette YAML files changed with the 0.4 release. Cassettes recorded with
|
407
|
-
older versions of VCR will not work with VCR 0.4.0 and later. However, VCR provides a rake task to migrate
|
408
|
-
your old cassettes to the new format--see the [changelog](http://github.com/myronmarston/vcr/blob/master/CHANGELOG.md)
|
409
|
-
for more info.
|
410
|
-
* The cassette name determines the name of the library file for the given cassette. Strings or symbols are fine,
|
411
|
-
and you can include any characters, but spaces and invalid file name characters will be removed
|
412
|
-
before the cassette reads or writes to its library file.
|
413
|
-
* You can use a directory separator (i.e. '/') in your cassette names to cause it to use a subdirectory
|
414
|
-
of the cassette library directory. The cucumber tagging support uses this.
|
415
|
-
* VCR maintains a simple stack of cassettes. This allows you to nest them as deeply as you want.
|
416
|
-
This is particularly useful when you have a cucumber step definition that uses a cassette, and
|
417
|
-
you also want to use a cassette for the entire scenario using the tagging support.
|
418
|
-
* If you find VCR useful, please recommend me on [working with rails](http://workingwithrails.com/person/16590-myron-marston).
|
66
|
+
If you find VCR useful, please recommend me on [working with rails](http://workingwithrails.com/person/16590-myron-marston).
|
419
67
|
|
420
68
|
## Thanks
|
421
69
|
|
@@ -424,6 +72,8 @@ VCR has been tested on the following ruby interpreters:
|
|
424
72
|
* [Chris Kampmeier](http://github.com/chrisk) for [FakeWeb](http://github.com/chrisk/fakeweb).
|
425
73
|
* [Chris Young](http://github.com/chrisyoung) for [NetRecorder](http://github.com/chrisyoung/netrecorder),
|
426
74
|
the inspiration for VCR.
|
75
|
+
* [David Balatero](https://github.com/dbalatero) for help with [Typhoeus](https://github.com/pauldix/typhoeus)
|
76
|
+
support.
|
427
77
|
|
428
78
|
Thanks also to the following people who have contributed patches or helpful suggestions:
|
429
79
|
|
@@ -432,17 +82,6 @@ Thanks also to the following people who have contributed patches or helpful sugg
|
|
432
82
|
* [Ben Hutton](http://github.com/benhutton)
|
433
83
|
* [Eric Allam](http://github.com/rubymaverick)
|
434
84
|
|
435
|
-
## Similar Libraries
|
436
|
-
|
437
|
-
If VCR doesn't meet your needs, please [open an issue](http://github.com/myronmarston/vcr/issues) and let me know
|
438
|
-
how VCR could be improved. You may also want to try one of these similar libraries:
|
439
|
-
|
440
|
-
* [Stale Fish](http://github.com/jsmestad/stale_fish)
|
441
|
-
* [NetRecorder](http://github.com/chrisyoung/netrecorder)
|
442
|
-
* [Ephemeral Response](http://github.com/sandro/ephemeral_response)
|
443
|
-
* [Net::HTTP Spy](http://github.com/martinbtt/net-http-spy)
|
444
|
-
* [WebFixtures](http://github.com/trydionel/web_fixtures)
|
445
|
-
|
446
85
|
## Copyright
|
447
86
|
|
448
87
|
Copyright (c) 2010 Myron Marston. See LICENSE for details.
|