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'
        ]
current_cassette

Return the cassette that is currently in use.

Returns:Cassette
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:
  • placeholder (str) – (required), text to be used as a placeholder
  • replace (str) – (required), text to be replaced or replacing the placeholder

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 of setUp, 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')