Skip to content

kafeinnet/pytest-pvcr

Repository files navigation

pytest-pvcr

PyPI version Python versions License

A pytest plugin that records and replays commands executed with subprocess.run(), inspired by VCR.py.

Installation

pip install pytest-pvcr

Usage

Mark your tests with @pytest.mark.pvcr() and run them:

import subprocess
import pytest

@pytest.mark.pvcr()
def test_ls():
    ret = subprocess.run(["ls", "/tmp"])
    assert ret.returncode == 0

@pytest.mark.pvcr(wait=False)
def test_slow_command():
    # On replay, pvcr won't sleep for the original command duration
    ret = subprocess.run(["sleep", "10"])
    assert ret.returncode == 0
pytest --pvcr-record-mode=new test_commands.py

Recordings are stored as YAML files in recordings/<module>/<test_name>.yaml.

Record modes

# Only record new commands not previously recorded (default)
pytest --pvcr-record-mode=new

# Replay only, never record
pytest --pvcr-record-mode=none

# Re-record all commands, even previously recorded ones
pytest --pvcr-record-mode=all

# Record on first run, then replay only and block unrecorded commands
pytest --pvcr-record-mode=once

The once mode is useful in CI: it records everything on the first run (when no recording file exists), then on subsequent runs it replays and raises PVCRBlockedRunException if an unrecorded command is encountered.

Block execution

Block all unrecorded subprocess calls, useful to protect test environments:

pytest --pvcr-block-run

Fuzzy matching

Fuzzy matching replaces variable parts of commands so recordings stay portable.

Via CLI (global, applies to all tests):

# Ignore `--dry-run` arguments when matching commands
pytest --pvcr-fuzzy-matcher='--dry-run'

# Keep only the filename from a path
pytest --pvcr-fuzzy-matcher='^.+\/(kubeconfig)$'

# Automatically ignore the parent directory of the test file
pytest --pvcr-auto-fuzzy-match

Via marker (per-test):

@pytest.mark.pvcr()
@pytest.mark.pvcr_fuzzy_matcher(r'^.+\/(config\.yml)$')
def test_with_fuzzy():
    subprocess.run(["cat", "/some/path/config.yml"])

If a regex has no capture groups, the matched string is replaced with a placeholder. If a regex has capture groups, the captured parts are kept and the rest is replaced.

Python support

Python >= 3.12

Authors

About

A pytest plugin that records and replays commands executed with `subprocess.run()`. This plugin is inspired by `VCR.py`.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages