Debugging¶
VCR.py has a few log messages you can turn on to help you figure out if HTTP requests are hitting a real server or not. You can turn them on like this:
import vcr
import requests
import logging
logging.basicConfig() # you need to initialize logging, otherwise you will not see anything from vcrpy
vcr_log = logging.getLogger("vcr")
vcr_log.setLevel(logging.INFO)
with vcr.use_cassette('headers.yml'):
requests.get('http://httpbin.org/headers')
The first time you run this, you will see:
INFO:vcr.stubs:<Request (GET) http://httpbin.org/headers> not in cassette, sending to real server
The second time, you will see:
INFO:vcr.stubs:Playing response for <Request (GET) http://httpbin.org/headers> from cassette
If you set the loglevel to DEBUG, you will also get information about which matchers didn’t match. This can help you with debugging custom matchers.
CannotOverwriteExistingCassetteException¶
VCR.py raises CannotOverwriteExistingCassetteException when a request
isn’t in the cassette and the record mode doesn’t allow recording it. The
message starts with what went wrong, then shows the request, the cassette’s
settings and, when it helps, the recorded requests closest to the one being
made, with how each of them differs. It ends with suggestions for fixing it.
For example, when the query string of a request changed:
CannotOverwriteExistingCassetteException: Can't play back this request: no recorded interaction matches it (the closest differ in query).
record_mode 'once' doesn't record new requests into an existing cassette.
GET https://www.googleapis.com/?alt=json&maxResults=200
Cassette: cassette.yaml
record_mode: once
match_on: method, scheme, host, port, path, query
interactions: 1 recorded, 0 played
Closest recorded requests:
1. GET https://www.googleapis.com/?alt=json&maxResults=500
query differs: [('alt', 'json'), ('maxResults', '200')] != [('alt', 'json'), ('maxResults', '500')]
How to fix:
* If the request changed on purpose, record it again: run once with
record_mode='new_episodes' to add it to the cassette, or record_mode='all'
with drop_unused_requests=True to re-record the cassette from scratch [1].
* If the difference changes on every run (a timestamp, a random ID), make
matching ignore it: loosen match_on, or normalize the request with
before_record_request [2].
[1] https://vcrpy.readthedocs.io/en/latest/usage.html#record-modes
[2] https://vcrpy.readthedocs.io/en/latest/configuration.html#request-matching
When a request body differs, the message shows a short diff of the bodies. At most three of the closest recorded requests are shown in full; the rest are summarized by how they differ.
The exception also has these attributes, for tools that want to report the problem themselves:
cassetteandfailed_request: the cassette and the request that couldn’t be handled.reason: why it couldn’t be handled."cassette_not_found"when the cassette file doesn’t exist (or couldn’t be loaded) and the record mode can’t create it,"already_played"when the matching recorded interactions have all been played back already,"no_match"when recorded requests are similar but none matches, and"nothing_similar"when nothing in the cassette is similar.similar_requests: the closest recorded requests, as(request, succeeded_matchers, failed_matchers)tuples, wherefailed_matchersis a list of(matcher_name, message)tuples.