ropensci / vcr

Record HTTP calls and replay them
https://docs.ropensci.org/vcr
Other
77 stars 12 forks source link

add fxn: use_cassettes #22

Open sckott opened 6 years ago

sckott commented 6 years ago
def use_cassettes(cassettes, &block)
  return use_cassette(cassettes.last[:name]) { block.call } if cassettes.length == 1
  cassette = cassettes.pop
  use_cassette(cassette[:name], cassette[:options]) do
    use_cassettes(cassettes, &block)
  end
end

(above has changed I think, in the vcr lib https://github.com/vcr/vcr/blob/master/lib/vcr.rb#L203-L222)

alex-gable commented 4 years ago

@sckott is this functionality possible given the current state of the package?

Should I be approaching the problem of needing two cassettes (created and tested separately) to test a third function in a different way?

sckott commented 4 years ago

it's not implemented yet

Should I be approaching the problem of needing two cassettes (created and tested separately) to test a third function in a different way?

can you explain that use case in more detail, not sure I follow.

alex-gable commented 4 years ago

I’ve got a function c that internally calls functionsa and b.

c makes no requests of its own. a makes a request and has its own cassette. b makes a request and has its own cassette.

In order to properly test the output of c, I need to ensure that when a and b are called, they return the contents of their cassette.

I suppose I could record a cassette for c, which would contain redundant copies of cassettes a and b.

I’m mostly just wondering how you’d approach this currently.

FWIW, my first approach was to just nest my use_cassette calls before executing the function, but it occurred to me that’s basically how the ruby implementation is set up. I’ll post back with how that goes.

sckott commented 4 years ago

Thanks, i see.

Looking at what Ruby does.

This use case makes sense, in which you have cassettes already created (below, foo and bar), and then you use those cassettes in a call to use_cassesttes

require 'vcr'
require 'faraday'
VCR.configure do |config|
  config.cassette_library_dir = "fixtures/vcr_cassettes"
  config.hook_into :webmock
end
conn = Faraday.new('https://httpbin.org') do |f|
  f.request :url_encoded
end
VCR.use_cassette("foo") do
  conn.get 'get', {query: 'salmon'}
end
VCR.use_cassette("bar") do
  conn.get 'get', {stuff: 'things'}
end
cassettes = [
  { name: 'foo' },
  { name: 'bar' }
]
VCR.use_cassettes(cassettes) do 
  conn.get 'get', {query: 'salmon'}
  conn.get 'get', {stuff: 'things'}
end

I've not been able to find much about use_cassettes on the web, so I'm not sure if other use cases are supposed to be supported by this method, e.g, this doesn't quite makes sense:

cassettes = [
  { name: 'thing1' },
  { name: 'thing2' }
]
VCR.use_cassettes(cassettes) do 
  conn.get 'get', {query: 'salmon'}
  conn.get 'get', {stuff: 'things'}
end

Both requests get recorded into the first cassette (thing1), and the second cassette has nothing in it.

Clearly the first use case with already recorded cassettes makes sense, but not sure if any other use cases should be supported

sckott commented 4 years ago

started working on https://github.com/ropensci/vcr/compare/use-cassettes - not working yet.

can't figure out how Ruby vcr makes it so that cassette request matching doesn't fail for http requests that don't go with each cassette. if you run use_cassetttes eg, it doesn't work

alex-gable commented 4 years ago

In the example you made above, if your aim was to only have the salmon query in the thing1 cassette, couldn’t you simply add the record:once option?

I don’t believe it’s a particularly elegant solution, but if I’m understanding vcr/vcr’s implementation correctly it would work. In all cases, it appears the order the cassettes are added to use_cassettes matters, and maybe that’s the trade off that needs to be made?

alex-gable commented 4 years ago

The lone test case in the original implementation seems to imply that the expected behavior would be using cassettes in an ordered manner.

https://github.com/vcr/vcr/blob/b38a38e6175af847f1c162e6bec29b9eadb12a9f/spec/lib/vcr_spec.rb#L355

sckott commented 4 years ago

couldn’t you simply add the record:once option?

perhaps, can try

Good point about order, BUT the block of code passed in AFAICT gets passed to each execution of use_cassette within use_cassettes, and that's where the error is coming from in R vcr. I don't quite understand how that doesn't cause an error in the ruby version. AFAICT the block of code that does HTTP requests

conn.get 'get', {query: 'salmon'}
conn.get 'get', {stuff: 'things'}

is passed as &block https://github.com/vcr/vcr/blob/master/lib/vcr.rb#L219 to each call to use_cassette - and i'm not sure why that doesn't error. Guessing there's. something different about the way use_cassette works in Ruby vs. R versions