Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to specify custom cassette path per test. #25

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ init:
- "%PYTHON%/python -c \"import struct;print( 8 * struct.calcsize(\'P\'))\""

install:
- "%PYTHON%/python -m pip install --upgrade pip"
- "%PYTHON%/python -m pip uninstall -y virtualenv"
- "%PYTHON%/Scripts/pip install virtualenv"
- "%PYTHON%/Scripts/easy_install -U pip"
- "%PYTHON%/Scripts/pip install tox"
- "%PYTHON%/Scripts/pip install wheel"
Expand Down
11 changes: 10 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def vcr(vcr):


# Marker options
All options provided on the marker will be passed to the VCR constructor, for example:
All options (keyword arguments) provided on the marker will be passed to the VCR constructor, for example:

```python
@pytest.mark.vcr(ignore_localhost=True)
Expand All @@ -65,3 +65,12 @@ def test_local_and_remote():
# This one will always be downloaded
urlopen('http://127.0.0.1/').read()
```

It is also posible to specify cassette name and path per test using path as marker first argument

```python
@pytest.mark.vcr("custom/path/iana.yaml")
def test_local_and_remote():
# This one will replay from the cassette
urlopen('http://www.iana.org/domains/reserved').read()
```
31 changes: 27 additions & 4 deletions pytest_vcr.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def _vcr_marker(request):
request.getfixturevalue('vcr_cassette')


def _has_custom_name(marker):
return marker and marker.args


def _update_kwargs(request, kwargs):
marker = request.node.get_closest_marker('vcr')
if marker:
Expand All @@ -62,9 +66,8 @@ def _update_kwargs(request, kwargs):
kwargs['before_record_response'] = lambda *args, **kwargs: None


@pytest.fixture(scope='module')
def vcr(request, vcr_config, vcr_cassette_dir, ):
"""The VCR instance"""
def _vcr(request, vcr_config, vcr_cassette_dir, ):
"""Create VCR instance"""
if request.config.getoption('--vcr-record-mode'):
warnings.warn("--vcr-record-mode has been deprecated and will be removed in a future "
"release. Use --vcr-record instead.",
Expand All @@ -79,11 +82,28 @@ def vcr(request, vcr_config, vcr_cassette_dir, ):
return vcr


@pytest.fixture(scope='module')
def vcr(request, vcr_config, vcr_cassette_dir, ):
"""The VCR instance, module level fixture"""
return _vcr(request, vcr_config, vcr_cassette_dir, )


@pytest.fixture
def vcr_per_test(request, vcr_config):
"""The VCR instance, function level fixture"""
return _vcr(request, vcr_config, None)


@pytest.fixture
def vcr_cassette(request, vcr, vcr_cassette_name):
def vcr_cassette(request, vcr_cassette_name):
"""Wrap a test in a VCR.py cassette"""
kwargs = {}
_update_kwargs(request, kwargs)
marker = request.node.get_closest_marker("vcr")
if _has_custom_name(marker):
vcr = request.getfixturevalue("vcr_per_test")
else:
vcr = request.getfixturevalue("vcr")
with vcr.use_cassette(vcr_cassette_name, **kwargs) as cassette:
yield cassette

Expand All @@ -97,6 +117,9 @@ def vcr_cassette_dir(request):
@pytest.fixture
def vcr_cassette_name(request):
"""Name of the VCR cassette"""
marker = request.node.get_closest_marker("vcr")
if _has_custom_name(marker):
return marker.args[0]
test_class = request.cls
if test_class:
return "{}.{}".format(test_class.__name__, request.node.name)
Expand Down
42 changes: 42 additions & 0 deletions tests/test_vcr.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,30 @@ def test_method(self, vcr_cassette_name):
result.stdout.fnmatch_lines(['*Cassette: TestClass.test_method'])


def test_cassette_custom_path(testdir):
testdir.makepyfile(
"""
import os
import pytest

@pytest.mark.vcr("custom/path.yaml")
def test_cassette_name(vcr_cassette_name, vcr_cassette):
assert "custom/path.yaml" == vcr_cassette._path
print("Cassette name: {}".format(vcr_cassette_name))

@pytest.mark.vcr
def test_no_path(vcr_cassette_name, vcr_cassette):
assert os.path.join("cassettes", "test_no_path.yaml") in vcr_cassette._path
print("Cassette name: {}".format(vcr_cassette_name))
"""
)

result = testdir.runpytest("-s")
result.assert_outcomes(2, 0, 0)
result.stdout.fnmatch_lines(['*Cassette name: custom/path.yaml'])
result.stdout.fnmatch_lines(['*Cassette name: test_no_path'])


def test_vcr_config(testdir):
testdir.makepyfile("""
import pytest
Expand Down Expand Up @@ -237,6 +261,24 @@ def test_method(vcr_cassette):
result.stdout.fnmatch_lines(['*Cassette record mode: none'])


def test_cassette_custom_path_marker_options(testdir):
testdir.makepyfile("""
import pytest

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

@pytest.mark.vcr("custom/path.yaml", record_mode='none')
def test_method(vcr_cassette):
print("Cassette record mode: {}".format(vcr_cassette.record_mode))
""")

result = testdir.runpytest('-s')
result.assert_outcomes(1, 0, 0)
result.stdout.fnmatch_lines(['*Cassette record mode: none'])


def test_overriding_record_mode(testdir):
testdir.makepyfile("""
import pytest
Expand Down