Search code examples
ruby-on-railsrubycucumbererbvcr

How to stop VCR from overwriting erb in the cassettes


We've recently started using VCR to stub requests in our cucumber tests. We're using cucumber tables to describe different kinds of requests, and storing them as variables with gherkin. Our cassette files have all been reworked to include erb, so that we can substitute in the values for the request we want to test.

The problem is that whenever there is a new request, VCR records the new requests and also overwrites (removes) all the erb from the cassette, replacing it with the request as interpolated for that example. Every time we run requests where a value has changed (say, the value of the timestamp we receive from the API we're talking to), all the erb needs to be copied back in to the cassette file. This is frustrating, since tests are run all the time.

Does anyone know why VCR strips the erb out when recording new responses? Any idea of a workaround? Is there any way to save back a template before it's interpolated?


Solution

  • Automatically merging your manual changes to the cassette with a newly recorded cassette is a difficult problem that, in my opinion, is best left to tools that are specifically designed to handle the history of text documents and manage merging them (i.e. your source control system). ERB makes it even more difficult: while you may just be using ERB to interpolate variables, any valid ruby can be used. There may be loops, conditionals and more in the ERB. There's no way for VCR to automatically merge this stuff.

    A couple suggestions:

    • Use your cassettes in a more granular fashion so that they do not get overridden frequently. I tend to use a casette for each HTTP request or logical group of HTTP requests.
    • Use the :once record mode (the recent default) to prevent existing cassettes from being overriden.
    • Take a look at the sensitive data filtering feature of VCR. This is far less flexible than ERB (i.e. you can't use loops, conditionals, or any arbitrary ruby code), but for simple variable intepolation, it works really, really well. Rather than using ERB, it uses a placeholder string--you might use a string like <PASSWORD> to take the place of a password, for example. VCR automatically takes care of inserting the placeholder text when it records the cassette, and replacing it with the correct real value on playback.
    • If that doesn't meet your needs, the before_record and before_playback hooks should give you all the power you need to do automatic interpolation (or even ERB snippet insertion) when a cassette is recorded. It's basically how the filtering works--see here.

    I'm certainly open to ideas for how to improve VCR if these things don't meet your needs.