Skip to main content

codecov Build Version Python versions License

A pytest plugin that allows to record network interactions via VCR.py.

Features

  • Straightforward pytest.mark.vcr, that reflects VCR.use_cassettes API;

  • Combining multiple VCR cassettes;

  • Network access blocking.

Usage

import pytest
import requests

# cassettes/{module_name}/test_single.yaml will be used
@pytest.mark.vcr
def test_single():
    assert requests.get("http://httpbin.org/get").text == '{"get": true}'

# these cassettes will be used in addition to the default one
@pytest.mark.vcr("/path/to/ip.yaml", "/path/to/get.yaml")
def test_multiple():
    assert requests.get("http://httpbin.org/get").text == '{"get": true}'
    assert requests.get("http://httpbin.org/ip").text == '{"ip": true}'

Configuration

The recording configuration could be provided with vcr_config fixture, which could be any scope - session, package, module or function. It should return a dictionary that will be passed directly to VCR.use_cassettes under the hood.

import pytest

@pytest.fixture(scope="module")
def vcr_config():
    return {"filter_headers": ["authorization"]}

For more granular control you need to pass these keyword arguments to individual pytest.mark.vcr marks, and in this case all arguments will be merged into a single dictionary with the following priority (low -> high):

  • vcr_config fixture

  • all marks from the most broad scope (“session”) to the most narrow one (“function”)

Example:

import pytest

pytestmark = [pytest.mark.vcr(ignore_localhost=True)]

@pytest.fixture(scope="module")
def vcr_config():
    return {"filter_headers": ["authorization"]}

@pytest.mark.vcr(filter_headers=[])
def test_one():
    ...

@pytest.mark.vcr(filter_query_parameters=["api_key"])
def test_two():
    ...

Resulting VCR configs for each test:

  • test_one - {"ignore_localhost": True, "filter_headers": []}

  • test_two - {"ignore_localhost": True, "filter_headers": ["authorization"], "filter_query_parameters": ["api_key"]}

You can get access to the used VCR instance via pytest_recording_configure hook. It might be useful for registering custom matchers, persisters, etc:

# conftest.py

def jurassic_matcher(r1, r2):
    assert r1.uri == r2.uri and "JURASSIC PARK" in r1.body, \
        "required string (JURASSIC PARK) not found in request body"

def pytest_recording_configure(config, vcr):
    vcr.register_matcher("jurassic", jurassic_matcher)

Rewrite record mode

It possible to rewrite cassette from scratch, and not to append as it is done with all record mode in current VCR.py implementation.

However, it will rewrite only the default first cassette, any extra cassettes provided will not be touched.

import pytest

@pytest.fixture(scope="module")
def vcr_config():
    return {"record_mode": "rewrite"}

Or via command line option:

$ pytest --record-mode=rewrite tests/

Blocking network access

To have more confidence that your tests will not go over the wire, you can block it with pytest.mark.block_network mark:

import pytest
import requests

@pytest.mark.block_network
def test_multiple():
    assert requests.get("http://httpbin.org/get").text == '{"get": true}'

...
# in case of access
RuntimeError: Network is disabled

Besides marks, the network access could be blocked globally with --block-network command-line option.

However, if VCR.py recording is enabled then, the network is not blocked for tests, that have pytest.mark.vcr.

Example:

import pytest
import requests

@pytest.mark.vcr
def test_multiple():
    assert requests.get("http://httpbin.org/get").text == '{"get": true}'

Run pytest:

$ pytest --record-mode=once --block-network tests/

The network blocking feature supports socket-based transports and pycurl.

It is possible to allow access to specified hosts during network blocking:

import pytest
import requests

@pytest.mark.block_network(allowed_hosts=["httpbin.*"])
def test_access():
    assert requests.get("http://httpbin.org/get").text == '{"get": true}'
    with pytest.raises(RuntimeError, match=r"^Network is disabled$"):
        requests.get("http://example.com")

Or via command line option:

$ pytest --record-mode=once --block-network --allowed-hosts=httpbin.*,localhost tests/

Contributing

To run the tests:

$ tox -p all

If you have troubles with installing pycurl with tox, you could try to pass CPPFLAGS and LDFLAGS with the tox command:

$  CPPFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib" tox -p all

Python support

Pytest-recording supports:

  • CPython 2.7, 3.5, 3.6, 3.7 and 3.8.

  • PyPy 7 (2.7 & 3.6)

License

The code in this project is licensed under MIT license. By contributing to pytest-recording, you agree that your contributions will be licensed under its MIT license.

Release files for pytest-recording 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-recording 0.8.0
File Size Uploaded
pytest-recording-0.8.0.tar.gz 10.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-recording 0.8.0
File Interpreter ABI Platform
pytest_recording-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.2 kB

Release files / pytest-recording-0.8.0.tar.gz

Download URL pytest-recording-0.8.0.tar.gz
Size 10.0 kB
Tags Source
SHA-256 checksum
How to use checksums
4d7dfff8262fec134a13f030c91f9949f6085503757a2c88c727d4a77e90d4f7
BLAKE2b-256 checksum
How to use checksums
91fef54a43e47e55dde5dae0d6936b48bedc36b62976054235c1a083c349cd8e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.7.7

Release files / pytest_recording-0.8.0-py3-none-any.whl

Download URL pytest_recording-0.8.0-py3-none-any.whl
Size 10.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
079eb5ec2081a90051788e0863423023f5fbb46ec8ee56af686048f33a2db36e
BLAKE2b-256 checksum
How to use checksums
f1efd7f06eccf9dfa8a1b3e031671513b1ab0d50f5f74384e2e75170f6bdb8c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.7.7

Release history Release notifications | RSS feed

0.13.3

2 release files

0.13.0

2 release files

0.12.2

2 release files

0.12.1

2 release files

0.11.0

2 release files

0.9.0

1 release file

0.8.1

2 release files

This release

0.8.0 This release

2 release files

0.7.0

2 release files

0.6.0

1 release file

0.5.0

2 release files

0.4.0

2 release files

0.3.6

2 release files

0.3.5

1 release file

0.3.4

1 release file

0.3.3

1 release file

0.3.2

1 release file

0.3.1

1 release file

0.3.0

1 release file

0.2.0

1 release file

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page