API¶
-
class
betamax.
Betamax
(session, cassette_library_dir=None, default_cassette_options={})¶ This object contains the main API of the request-vcr library.
This object is entirely a context manager so all you have to do is:
s = requests.Session() with Betamax(s) as vcr: vcr.use_cassette('example') r = s.get('https://httpbin.org/get')
Or more concisely, you can do:
s = requests.Session() with Betamax(s).use_cassette('example') as vcr: r = s.get('https://httpbin.org/get')
This object allows for the user to specify the cassette library directory and default cassette options.
s = requests.Session() with Betamax(s, cassette_library_dir='tests/cassettes') as vcr: vcr.use_cassette('example') r = s.get('https://httpbin.org/get') with Betamax(s, default_cassette_options={ 're_record_interval': 1000 }) as vcr: vcr.use_cassette('example') r = s.get('https://httpbin.org/get')
-
betamax_adapter
= None¶ Create a new adapter to replace the existing ones
-
static
configure
()¶ Help to configure the library as a whole.
with Betamax.configure() as config: config.cassette_library_dir = 'tests/cassettes/' config.default_cassette_options['match_options'] = [ 'method', 'uri', 'headers' ]
-
http_adapters
= None¶ Store the session’s original adapters.
-
static
register_request_matcher
(matcher_class)¶ Register a new request matcher.
Parameters: matcher_class – (required), this must sub-class BaseMatcher
-
static
register_serializer
(serializer_class)¶ Register a new serializer.
Parameters: matcher_class – (required), this must sub-class BaseSerializer
-
session
= None¶ Store the requests.Session object being wrapped.
-
start
()¶ Start recording or replaying interactions.
-
stop
()¶ Stop recording or replaying interactions.
-
use_cassette
(cassette_name, **kwargs)¶ Tell Betamax which cassette you wish to use for the context.
Parameters: - cassette_name (str) – relative name, without the serialization format, of the cassette you wish Betamax would use
- serialize_with (str) – the format you want Betamax to serialize the cassette with
- serialize (str) – DEPRECATED the format you want Betamax to serialize the request and response data to and from
-
-
betamax.decorator.
use_cassette
(cassette_name, cassette_library_dir=None, default_cassette_options={}, **use_cassette_kwargs)¶ Provide a Betamax-wrapped Session for convenience.
New in version 0.5.0.
This decorator can be used to get a plain Session that has been wrapped in Betamax. For example,
from betamax.decorator import use_cassette @use_cassette('example-decorator', cassette_library_dir='.') def test_get(session): # do things with session
Parameters: - cassette_name (str) – Name of the cassette file in which interactions will be stored.
- cassette_library_dir (str) – Directory in which cassette files will be stored.
- default_cassette_options (dict) – Dictionary of default cassette options to set for the cassette used when recording these interactions.
- **use_cassette_kwargs – Keyword arguments passed to
use_cassette()
-
class
betamax.configure.
Configuration
¶ This object acts as a proxy to configure different parts of Betamax.
You should only ever encounter this object when configuring the library as a whole. For example:
with Betamax.configure() as config: config.cassette_library_dir = 'tests/cassettes/' config.default_cassette_options['record_mode'] = 'once' config.default_cassette_options['match_requests_on'] = ['uri'] config.define_cassette_placeholder('<URI>', 'http://httpbin.org') config.preserve_exact_body_bytes = True
-
after_start
(callback=None)¶ Register a function to call after Betamax is started.
Example usage:
def on_betamax_start(cassette): if cassette.is_recording(): print("Setting up authentication...") with Betamax.configure() as config: config.cassette_load(callback=on_cassette_load)
Parameters: callback (callable) – The function which accepts a cassette and might mutate it before returning.
-
before_playback
(tag=None, callback=None)¶ Register a function to call before playing back an interaction.
Example usage:
def before_playback(interaction, cassette): pass with Betamax.configure() as config: config.before_playback(callback=before_playback)
Parameters: - tag (str) – Limits the interactions passed to the function based on the interaction’s tag (currently unsupported).
- callback (callable) – The function which either accepts just an interaction or an interaction and a cassette and mutates the interaction before returning.
-
before_record
(tag=None, callback=None)¶ Register a function to call before recording an interaction.
Example usage:
def before_record(interaction, cassette): pass with Betamax.configure() as config: config.before_record(callback=before_record)
Parameters: - tag (str) – Limits the interactions passed to the function based on the interaction’s tag (currently unsupported).
- callback (callable) – The function which either accepts just an interaction or an interaction and a cassette and mutates the interaction before returning.
-
before_stop
(callback=None)¶ Register a function to call before Betamax stops.
Example usage:
def on_betamax_stop(cassette): if not cassette.is_recording(): print("Playback completed.") with Betamax.configure() as config: config.cassette_eject(callback=on_betamax_stop)
Parameters: callback (callable) – The function which accepts a cassette and might mutate it before returning.
-
cassette_library_dir
¶ Retrieve and set the directory to store the cassettes in.
-
default_cassette_options
¶ Retrieve and set the default cassette options.
The options include:
match_requests_on
placeholders
re_record_interval
record_mode
preserve_exact_body_bytes
Other options will be ignored.
-
define_cassette_placeholder
(placeholder, replace)¶ Define a placeholder value for some text.
This also will replace the placeholder text with the text you wish it to use when replaying interactions from cassettes.
Parameters:
-
A set of fixtures to integrate Betamax with py.test.
-
betamax.fixtures.pytest.
betamax_session
(betamax_recorder)¶ Generate a session that has Betamax already installed.
See betamax_recorder fixture.
Parameters: betamax_recorder – A recorder fixture with a configured request session. Returns: An instantiated requests Session wrapped by Betamax.
Minimal unittest.TestCase
subclass adding Betamax integration.
-
class
betamax.fixtures.unittest.
BetamaxTestCase
(methodName='runTest')¶ Betamax integration for unittest.
New in version 0.5.0.
-
CASSETTE_LIBRARY_DIR
= None¶ Custom path to save cassette.
-
SESSION_CLASS
¶ alias of
requests.sessions.Session
-
generate_cassette_name
()¶ Generates a cassette name for the current test.
The default format is “%(classname)s.%(testMethodName)s”
To change the default cassette format, override this method in a subclass.
Returns: Cassette name for the current test. Return type: str
-
setUp
()¶ Betamax-ified setUp fixture.
This will call the superclass’ setUp method first and then it will create a new
requests.Session
and wrap that in a Betamax object to record it. At the end ofsetUp
, it will start recording.
-
tearDown
()¶ Betamax-ified tearDown fixture.
This will call the superclass’ tearDown method first and then it will stop recording interactions.
-
When using Betamax with unittest, you can use the traditional style of Betamax
covered in the documentation thoroughly, or you can use your fixture methods,
unittest.TestCase.setUp()
and unittest.TestCase.tearDown()
to wrap
entire tests in Betamax.
Here’s how you might use it:
from betamax.fixtures import unittest
from myapi import SessionManager
class TestMyApi(unittest.BetamaxTestCase):
def setUp(self):
# Call BetamaxTestCase's setUp first to get a session
super(TestMyApi, self).setUp()
self.manager = SessionManager(self.session)
def test_all_users(self):
"""Retrieve all users from the API."""
for user in self.manager:
# Make assertions or something
Alternatively, if you are subclassing a requests.Session
to provide
extra functionality, you can do something like this:
from betamax.fixtures import unittest
from myapi import Session, SessionManager
class TestMyApi(unittest.BetamaxTestCase):
SESSION_CLASS = Session
# See above ...
Examples¶
Basic Usage¶
Let example.json be a file in a directory called cassettes with the content:
{
"http_interactions": [
{
"request": {
"body": {
"string": "",
"encoding": "utf-8"
},
"headers": {
"User-Agent": ["python-requests/v1.2.3"]
},
"method": "GET",
"uri": "https://httpbin.org/get"
},
"response": {
"body": {
"string": "example body",
"encoding": "utf-8"
},
"headers": {},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://httpbin.org/get"
}
}
],
"recorded_with": "betamax"
}
The following snippet will not raise any exceptions
from betamax import Betamax
from requests import Session
s = Session()
with Betamax(s, cassette_library_dir='cassettes') as betamax:
betamax.use_cassette('example', record='none')
r = s.get("https://httpbin.org/get")
On the other hand, this will raise an exception:
from betamax import Betamax
from requests import Session
s = Session()
with Betamax(s, cassette_library_dir='cassettes') as betamax:
betamax.use_cassette('example', record='none')
r = s.post("https://httpbin.org/post",
data={"key": "value"})
Finally, we can also use a decorator in order to simplify things:
import unittest
from betamax.decorator import use_cassette
class TestExample(unittest.TestCase):
@use_cassette('example', cassette_library_dir='cassettes')
def test_example(self, session):
session.get('https://httpbin.org/get')
# Or if you're using something like py.test
@use_cassette('example', cassette_library_dir='cassettes')
def test_example_pytest(session):
session.get('https://httpbin.org/get')
Opinions at Work¶
If you use requests
’s default Accept-Encoding
header, servers that
support gzip content encoding will return responses that Betamax cannot
serialize in a human-readable format. In this event, the cassette will look
like this:
{
"http_interactions": [
{
"request": {
"body": {
"base64_string": "",
"encoding": "utf-8"
},
"headers": {
"User-Agent": ["python-requests/v1.2.3"]
},
"method": "GET",
"uri": "https://httpbin.org/get"
},
"response": {
"body": {
"base64_string": "Zm9vIGJhcgo=",
"encoding": "utf-8"
},
"headers": {
"Content-Encoding": ["gzip"]
},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://httpbin.org/get"
}
}
],
"recorded_with": "betamax"
}
Forcing bytes to be preserved¶
You may want to force betamax to preserve the exact bytes in the body of a response (or request) instead of relying on the opinions held by the library. In this case you have two ways of telling betamax to do this.
The first, is on a per-cassette basis, like so:
from betamax import Betamax
import requests
session = Session()
with Betamax.configure() as config:
c.cassette_library_dir = '.'
with Betamax(session).use_cassette('some_cassette',
preserve_exact_body_bytes=True):
r = session.get('http://example.com')
On the other hand, you may want to preserve exact body bytes for all cassettes. In this case, you can do:
from betamax import Betamax
import requests
session = Session()
with Betamax.configure() as config:
c.cassette_library_dir = '.'
c.preserve_exact_body_bytes = True
with Betamax(session).use_cassette('some_cassette'):
r = session.get('http://example.com')