Skip to content

Commit

Permalink
module, tests: set up VCR.py for plugin example tests
Browse files Browse the repository at this point in the history
* Add new `vcr` kwarg to `module.example` decorator
  * Considered making this part of `online`, but decided to keep it
    separate as it would be a pretty big behavior change
* Add PyPI requirements for implementing VCR
  * This involved some trial-and-error, letting Travis flag up
    incompatibilities on old Python releases I can't install locally
* Configure default cassette directory for VCR via new conftest fixture
  • Loading branch information
dgw committed May 19, 2020
1 parent a687ab7 commit b0df1f2
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ quality:
test:
coverage run -m py.test -v .

test_novcr:
coverage run -m py.test -v . --vcr-record=none

coverage_report:
coverage report

Expand All @@ -16,7 +19,7 @@ coverages: coverage_report coverage_html

qa: quality test coverages

travis: quality test coverage_report
travis: quality test_novcr coverage_report

clean_docs:
$(MAKE) -C docs clean
Expand Down
12 changes: 12 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

import pytest

# This file lists files which should be ignored by pytest
Expand All @@ -24,3 +26,13 @@ def pytest_configure(config):
'markers',
'online: for tests that require online access. '
'Use --offline to skip them.')


@pytest.fixture(scope='module')
def vcr_cassette_dir(request):
# Override VCR.py cassette save location, to keep them out of code folders
parts = request.module.__name__.split('.')
if parts[0] == 'sopel':
# We know it's part of Sopel...
parts = parts[1:]
return os.path.join('test', 'vcr', *parts)
12 changes: 10 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
pytest<3.3; python_version == '3.3'
pytest>=4.6,<4.7; python_version != '3.3'
coveralls
flake8<3.6.0; python_version == '3.3'
flake8>=3.7.0,<3.8.0; python_version != '3.3'
flake8-coding
flake8-future-import<0.4.6
flake8-import-order; python_version > '3.3'
flake8-import-order<=1.18.1; python_version <= '3.3'
pytest<3.3; python_version == '3.3'
pytest>=4.6,<4.7; python_version != '3.3'
pytest-vcr==1.0.2; python_version != '3.3'
pytest-vcr==0.3.0; python_version == '3.3'
PyYAML<5.1; python_version == '3.3'
PyYAML<5.3; python_version == '3.4'
setuptools<40.0; python_version == '3.3'
sphinx
sphinxcontrib-autoprogram
vcrpy==2.1.1; python_version == '2.7'
vcrpy<1.12.0; python_version == '3.3'
vcrpy<2.1.0; python_version == '3.4'
vcrpy<3.0.0; python_version >= '3.5'
28 changes: 21 additions & 7 deletions sopel/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,9 +736,11 @@ class example(object):
:param bool user_help: whether this example should be included in
user-facing help output such as `.help command`
(optional; default ``False``; see below)
:param bool online: if ``True``, |pytest|_ will mark this
example as "online" (optional; default ``False``; see
below)
:param bool online: if ``True``, |pytest|_ will mark this example as
"online" (optional; default ``False``; see below)
:param bool vcr: if ``True``, this example's HTTP requests & responses will
be recorded for later reuse (optional; default ``False``;
see below)
.. |pytest| replace:: ``pytest``
.. _pytest: https://pypi.org/project/pytest/
Expand Down Expand Up @@ -766,13 +768,21 @@ class example(object):
can override this choice or include multiple examples by passing
``user_help=True`` to one or more ``example`` decorator(s).
Finally, passing ``online=True`` makes that particular example skippable if
Sopel's test suite is run in offline mode, which is mostly useful to make
life easier for other developers working on Sopel without Internet access.
Passing ``online=True`` makes that particular example skippable if Sopel's
test suite is run in offline mode, which is mostly useful to make life
easier for other developers working on Sopel without Internet access.
Finally, ``vcr=True`` records the example's HTTP requests and responses for
replaying during later test runs. It can be an alternative (or complement)
to ``online``, and is especially useful for testing plugin code that calls
on inconsistent or flaky remote APIs. The recorded "cassettes" of responses
can be committed alongside the code for use by CI services, etc. (See
`VCR.py <https://github.com/kevin1024/vcrpy>`_ & `pytest-vcr
<https://github.com/ktosiek/pytest-vcr>`_)
"""
def __init__(self, msg, result=None, privmsg=False, admin=False,
owner=False, repeat=1, re=False, ignore=None,
user_help=False, online=False):
user_help=False, online=False, vcr=False):
# Wrap result into a list for get_example_test
if isinstance(result, list):
self.result = result
Expand All @@ -787,6 +797,7 @@ def __init__(self, msg, result=None, privmsg=False, admin=False,
self.owner = owner
self.repeat = repeat
self.online = online
self.vcr = vcr

if isinstance(ignore, list):
self.ignore = ignore
Expand Down Expand Up @@ -820,6 +831,9 @@ def __call__(self, func):
if self.online:
test = pytest.mark.online(test)

if self.vcr:
test = pytest.mark.vcr(test)

sopel.test_tools.insert_into_module(
test, func.__module__, func.__name__, 'test_example'
)
Expand Down

0 comments on commit b0df1f2

Please sign in to comment.