/pytest-recording

A pytest plugin that allows recording network interactions via VCR.py

Primary LanguagePythonMIT LicenseMIT

pytest-recording

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

@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}'

# 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}'

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"]}

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=all --block-network tests/

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

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.