Skip to content

Commit

Permalink
Merge pull request #1926 from praw-dev/remove_unused_cassettes
Browse files Browse the repository at this point in the history
Remove unused cassettes
  • Loading branch information
LilSpazJoekp committed Dec 26, 2022
2 parents a586c29 + 57cd15d commit 1464552
Show file tree
Hide file tree
Showing 16 changed files with 1,559 additions and 4,347 deletions.
27 changes: 22 additions & 5 deletions docs/package_info/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,23 @@ to first delete it, and then rerun the test suite.
Please always verify that only the requests you expect to be made are contained within
your cassette.

If you are using a single cassette for multiple tests, you need to add a
``use_cassette`` pytest mark decorator. If you need specify parameters for the
``Betamax.use_cassette`` method, use the ``recorder_kwargs`` pytest mark decorator. The
``recorder_kwargs`` can be applied to a test class and/or individual test functions. For
example:
There are a few pytest markers that can be used to control how cassettes are recorded or
used.

- ``@pytest.mark.add_placeholder``: Allows you to add custom placeholders to the
cassette. This can be useful when you want to record dynamic or generated data, but do
not want it to be saved in the cassette. This marker takes at least one keyword
argument and can be applied to a test class or individual test methods. It can also be
applied multiple times.
- ``@pytest.mark.cassette_name``: Allows you to set the cassette name. This can be
useful when you want to use a cassette that was recorded by another test.
- ``@pytest.mark.recorder_kwargs``: Allows you to pass additional arguments to the
recorder. This can be useful if you need to specify parameters for the
``Betamax.use_cassette`` method. Like the ``add_placeholder`` marker, this marker can
be applied to a test class or individual test methods and can be applied multiple
times.

Examples:

.. code-block:: python
Expand All @@ -246,6 +258,11 @@ example:
def test_example__different_assertion(self):
...
@pytest.mark.add_placeholder(generated_data_a=generate_data_a())
@pytest.mark.add_placeholder(generated_data_b=generate_data_b())
def test_example__with_generated_placeholders(self):
...
Documentation
-------------

Expand Down
3 changes: 3 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ def _get_path(name):

def pytest_configure(config):
pytest.placeholders = Placeholders(placeholders)
config.addinivalue_line(
"markers", "add_placeholder: Define an additional placeholder for the cassette."
)
config.addinivalue_line(
"markers", "cassette_name: Name of cassette to use for test."
)
Expand Down
54 changes: 26 additions & 28 deletions tests/integration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,34 @@
class IntegrationTest:
"""Base class for PRAW integration tests."""

@pytest.fixture(autouse=True, scope="session")
def cassette_tracker(self):
"""Track cassettes to ensure unused cassettes are not uploaded."""
global existing_cassettes
for cassette in os.listdir(CASSETTES_PATH):
existing_cassettes.add(cassette[: cassette.rindex(".")])
yield
unused_cassettes = existing_cassettes - used_cassettes
if unused_cassettes and os.getenv("ENSURE_NO_UNUSED_CASSETTES", "0") == "1":
raise AssertionError(
f"The following cassettes are unused: {', '.join(unused_cassettes)}."
)

@pytest.fixture(autouse=True)
def cassette(self, request, recorder, cassette_name):
"""Wrap a test in a VCR.py cassette"""
"""Wrap a test in a Betamax cassette."""
global used_cassettes
kwargs = {}
for marker in request.node.iter_markers("add_placeholder"):
for key, value in marker.kwargs.items():
recorder.config.default_cassette_options["placeholders"].append(
{"placeholder": f"<{key.upper()}>", "replace": value}
)
for marker in request.node.iter_markers("recorder_kwargs"):
if marker is not None:
append_placeholders = marker.kwargs.pop("append_placeholders", None)
if append_placeholders is not None:
recorder.config.default_cassette_options["placeholders"].append(
append_placeholders
)
for key, value in marker.kwargs.items():
# Don't overwrite existing values since function markers are
# provided before class markers.
kwargs.setdefault(key, value)
for key, value in marker.kwargs.items():
# Don't overwrite existing values since function markers are provided
# before class markers.
kwargs.setdefault(key, value)
with recorder.use_cassette(cassette_name, **kwargs) as recorder:
cassette = recorder.current_cassette
if cassette.is_recording():
Expand All @@ -50,18 +62,18 @@ def cassette(self, request, recorder, cassette_name):

@pytest.fixture(autouse=True)
def read_only(self, reddit):
"""Make reddit instance read-only."""
"""Make the Reddit instance read-only."""
# Require tests to explicitly disable read_only mode.
reddit.read_only = True

@pytest.fixture(autouse=True)
def recorder(self):
"""Configure VCR instance."""
"""Configure Betamax."""
session = requests.Session()
recorder = betamax.Betamax(session)
recorder.register_serializer(PrettyJSONSerializer)
with betamax.Betamax.configure() as config:
config.cassette_library_dir = "tests/integration/cassettes"
config.cassette_library_dir = CASSETTES_PATH
config.default_cassette_options["serialize_with"] = "prettyjson"
config.before_record(callback=filter_access_token)
for key, value in pytest.placeholders.__dict__.items():
Expand All @@ -72,20 +84,6 @@ def recorder(self):
# since placeholders persist between tests
Cassette.default_cassette_options["placeholders"] = []

@pytest.fixture(scope="session")
def cassette_tracker(self):
"""Return a dictionary to track cassettes."""
global existing_cassettes
for cassette in os.listdir(CASSETTES_PATH):
if cassette.endswith(".json"):
existing_cassettes.add(cassette.replace(".json", ""))
yield
unused_cassettes = existing_cassettes - used_cassettes
if unused_cassettes and os.getenv("ENSURE_NO_UNUSED_CASSETTES", "0") == "1":
raise AssertionError(
f"The following cassettes are unused: {', '.join(unused_cassettes)}."
)

@pytest.fixture
def cassette_name(self, request):
"""Return the name of the cassette to use."""
Expand Down
311 changes: 0 additions & 311 deletions tests/integration/cassettes/TestReddit.test_get_bulk_notes.json

This file was deleted.

0 comments on commit 1464552

Please sign in to comment.