Recently we have used VCR as part of our testing procedure for the court finder project. This has brought numerous benefits such as:
-
increasing the adoption of sensible defaults and development of a common style of testing web services
-
allowing us to run tests faster
-
allowing us to run tests more consistently, stubbing out external APIs in an automated fashion
-
allowing us to create predictable and accurate stubs, as a result of creating cassettes from actual API responses
What is VCR?
VCR is not in fact a Video-Cassette-Recorder! It’s a library by Myron Marston that can be used to improve the speed and reliability of tests by recording the interaction of an HTTP with an external web service.
This interaction is recorded to aptly named 'cassettes'. VCR is able to replay these cassettes which mocks the real request and response and enables offline testing of the web service API.
Using VCR, therefore, means that testing how your application interacts with external services is predictable, quick and accurate.
If your Ruby-on-Rails application relies on external web services, then you’ve probably noticed how slow testing can become. Using VCR helps to speed up testing, giving you more time to focus on development instead.
Setting up VCR
To get started with VCR, add the following to your Gemfile:
group :test do gem 'webmock', '= 1.15.2' gem 'vcr' end
It is important to include VCR and its mocking partner (in this case webmock) to the test group. It’s not a good idea to include VCR to development group as it will interrupt every web request during development.
We used the webmock version 1.15.2 on the court finder project as we had to properly align with other libraries and gems. It’s worth checking the correct version for your project before you start.
How it works
VCR utilises request matchers to match previously recorded HTTP requests to play back. Once the cassette has been recorded, it can be reused in future tests. Find out more here.
VCR.use_cassette(postcode_found, :record => :new_episodes) do response = Net::HTTP.get_response(mapit.com', '/postcode) puts "Response: #{response.body}" end
During development/testing, it’s a good idea to set the record option to ‘new_episodes’ as this allows the recording to continue behind the scenes as you work.
Once VCR has recorded what is required, it will then play it back. We moved our recording settings to the VCR configure block for wider reach and adoption across the project but there are other recording configuration modes. You find out more here.
VCR and court finder
We began using VCR after several production releases during the court finder project following an initial gem dependency mismatch issue.
require 'vcr' VCR.configure do |config| config.default_cassette_options = {:record => :new_episodes, :serialize_with => :json} config.cassette_library_dir = 'spec/fixtures/cassettes' config.hook_into :webmock config.ignore_hosts '127.0.0.1' # allow selenium/capybara to do its thing end
One of our first steps was to change the default cassette format to JSON. This is because cassettes are initially defined in yaml format, but yaml did not fit with our project due to conflicts with other gems which used Psych. Using JSON meant downgrading or upgrading certain gems and meant that VCR could run smoothly.
We also chose to configure our VCR within the spec_helper.rb file, because we wanted it to be available as we continued development and testing to trap http requests that were not VCR aware.
Once these basic configuration issues were understood and fixed, we were able to use VCR with court finder and create faster, more reliable tests to ensure a more reliable product can be released faster.
Leave a comment