> I've got _lots_ of tests that make third party HTTP calls, all of
> which I want to wrap with VCR. In a test::unit suite, it seems that
> every single one must be wrapped in a `use_cassette'.
> That's a whole lot of typing, for my many many tests.
VCR makes it easy to make virtually all your tests integration tests,
where HTTP requests are made all over the place, but I'd encourage you
not to do this. Instead, try to limit the number of tests that need
to use VCR by being limiting it to two kinds of tests:
* Wrap all 3rd party API access in objects you own. Make these
objects have a simple, well-defined interface that speaks in the
domain of your system. When you test these objects, use VCR.
* Use VCR for full-stack acceptance tests.
For all the other tests (e.g. tests of objects that collaborate w/
your 3rd party API wrappers) use a test double in place of your 3rd
party API wrappers. If you design them properly, with a small, simple
interface, this should be relatively easy to do.
For more on this topic, I encourage you to check out these resources:
*
https://github.com/craigw/craigw.github.com/blob/79e78a800907adb5d7c0a44af6484f1ca5f03510/_drafts/2012-04-10-my-thoughts-on-vcr.md
* The sucks/rock series on destroy all software, particularly
https://www.destroyallsoftware.com/screencasts/catalog/sucks-rocks-3-the-search-engine
> Additionally,
> in the default :once configuration, every one of these needs to be a
> _different_ cassette name too. That's a lot of cassettes.
That's actually not true. Multiple tests can re-use the same cassette
as long as they make the same sequence of requests. In general, it's
a good idea to map one cassette to one sequence of requests.
> Am I doing something wrong/weird, or is this how VCR's expecting
> people to use it with Test::Unit? Do people using with rspec have
> advantage of certain things that make this more tolerable, what ends
> up happening there?
In general, VCR makes relatively few expectations about how you should
or should not use VCR. The main API is `VCR.use_cassette` (as your
example uses) because this is a general API that is coupled to
_nothing_ (and can work outside of a test framework, in fact) and can
work _anywhere_. However, as you point out, it can be verbose to
manually use this everywhere. High-level abstractions are certainly
possible, and in fact encouraged. VCR itself ships with a couple of
the higher-level abstractions in the form of the RSpec and Cucumber
integration:
*
https://www.relishapp.com/myronmarston/vcr/v/2-1-1/docs/test-frameworks/usage-with-rspec-metadata
*
https://www.relishapp.com/myronmarston/vcr/v/2-1-1/docs/test-frameworks/usage-with-rspec-macro
*
https://www.relishapp.com/myronmarston/vcr/v/2-1-1/docs/test-frameworks/usage-with-cucumber
This is possible because RSpec and cucumber (and especially RSpec)
provide a rich API full of extension points for something like VCR to
hook into in a generic way. Test::Unit does not provide any similar
set of hooks, so there's no way for VCR to hook into it in a generic
way, and you're essentially on your own there.
The `test_with_cassette` method you pasted looks pretty reasonable,
but you may also want to consider writing helper methods are higher-
level versions of `VCR.use_cassette` specific to your domain. For
example, if your app made lots of API requests to github and did stuff
with repositories a lot, you might want a helper method like:
def use_github_cassette(user, repo)
VCR.use_cassette("github/#{user}/#{repo}") do
yield # or maybe even do something here to make the request
directly
end
end
> It seems that the way you erase tapes and
> re-record with VCR is simply by erasing the cassette.yml on disk?
This is one simple way, yes. You can also temporarily change the
record mode to :all or use the :re_record_interval option.
> I looked around, but I don't _think_ there's any way to erase/re-
> record just certain casettes based on a tag, right?
Not currently, no. No one's ever asked for that before.
> Is it possible to have cassetes be in sub-directories of your
> main cassette_library_dir
Yep, if you use a cassette name like "foo/bar/bazz", then the file
will be "foo/bar/bazz.yml" relative to the cassette_library_dir. I
use this all the time to arrange my cassettes.
HTH,
Myron