Skip to main content

Bust functools.lru_cache when running pytest to avoid test pollution

Project description

pytest-antilru

supported python versions license Code style: black

Build Status Coverage Status

More badges

latest version available on PyPI pypi wheels PyPI download count

open issues number of files code size repo size

Caching expensive function calls with functools.lru_cache is simple and great performance optimization. It works so well that it'll even speed up your unit test runs! Too bad it violated test isolation and caches the wrong values under test conditions, introducing test pollution (persisted state between test runs). This package will bust the lru_cache between test runs, avoiding test pollution and helping you keep your sanity.

Imagine you mock a network call out and your application ends up caching these mocked results:

def expensive_network_call() -> int:
    # Pretend this is an expensive network call.
    # You want to cache this for performance but you want to run tests with different responses as well.
    return 1


@lru_cache()
def cache_me() -> int:
    return expensive_network_call()

Now you have test pollution:

def test_a_run_first() -> None:
    assert cache_me() == 1


def test_b_run_second() -> None:
    # We want to mock the network call for this test case
    with mock.patch.object(sys.modules[__name__], 'expensive_network_call', return_value=2) as mock_network_call:
        assert cache_me() == 2
        assert mock_network_call.called

On your next test run, it doesn't matter what you mock, the results are already cached. Now trying running those two test out-of-order sequence and tell me how it goes.

Dependencies

Since this is a pytest plugin, you need to be using pytest to run your tests.

Compatibility

Current releases (>=2.0) support Python >=3.9. If you need Python <3.9, use an older pytest-antilru release line instead.

The supported pytest bands for current releases are:

  • Python 3.9: pytest >=3,<9
  • Python 3.10+: pytest >=3,<10

Pytest 9 is tested only on Python 3.10+.

The tox matrix in [tox.ini] and CI exercise these compatibility bands, including Python 3.14 coverage.

While we aim to support a wide range of Python and pytest combinations, pytest only allows its latest releases to support new interpreters: they do not patch older releases to work with newer Python versions. See [tox.ini] for the full envlist of what is being tested, and see the existing allowlist docs in the lru_cache_disabled section for compatibility-related configuration guidance.

If you experience issues, please check for compatibility between your python and pytest target versions. Open an issue once these are verified.

Installation

Simply install this in the same python environment that pytest uses and the rest is magic.

pip install pytest-antilru

Development setup

The runtime support for this package is Python >=3.9. For local contributor workflows, we recommend Python >=3.13 with uv.

Recommended setup after cloning:

make setup

This does two things for contributors:

  • installs the project dev environment with uv sync
  • installs git hooks with pre-commit install --install-hooks

If you prefer the raw commands:

uv sync
uv run pre-commit install --install-hooks

If you only want the project dev environment without git hook installation:

make venv

Poetry remains supported for legacy workflows, but is deprecated in favor of uv. When dependencies change, make lock runs both uv and poetry lock commands.

Legacy Poetry commands:

poetry lock
poetry sync

Configuration

Add this where ever your pytest configurations live.

lru_cache_disabled

lru_cache_disabled is an allowlist of module paths to disable lru_cache for. This allows you to target disable caching for specific modules that are causing test pollution.

The default behaviour of pytest-antilru is to disable lru_cache everywhere. However, this can interfere with other dependencies that are reliant on lru_cache behaviour to behave correctly within the same test run.

[tool.pytest.ini_options]
lru_cache_disabled = '''
    my_module.util
    my_module.client_lib.database
    '''

In this example, any usage of lru_cache in a file inside my_module.util or my_module.client_lib.database will be disabled. All other instances will continue to be cached within a test run.

How to test the software

make test

This validates the pre-commit checks with pre-commit run --all-files, but it does not install git hooks for you. Run make setup once on a new clone so local commits are checked before push.


Credits and references

This project was a re-engineering of a similar project a colleague of mine wrote. That project was not intended to be open-source and rather than go though all the hoops and hurdles to sanitize it, I've written it from the ground up such that it's kosher to open-source (given that it's such as small project).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest_antilru-2.0.1.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_antilru-2.0.1-py2.py3-none-any.whl (6.5 kB view details)

Uploaded Python 2Python 3

File details

Details for the file pytest_antilru-2.0.1.tar.gz.

File metadata

  • Download URL: pytest_antilru-2.0.1.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.7

File hashes

Hashes for pytest_antilru-2.0.1.tar.gz
Algorithm Hash digest
SHA256 92aa12a73e3bc4da2ead8c15602a9249ea3a0fc5fc7861d7215c50024ced4bd4
MD5 f6ded0d858b95260c2e67f3f32fa3ae1
BLAKE2b-256 7a2a0f48522b86464d9db03c3a2301e05e084512c0dfed5a81aa36fde39cce40

See more details on using hashes here.

File details

Details for the file pytest_antilru-2.0.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_antilru-2.0.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 5e23fc5059f27195ccf837f3331837ca0ff0c6b2aa535fe16e2f42471fdefc97
MD5 32eb763f0a0fbe43774c8ad8e8bb20a3
BLAKE2b-256 e9178f4e67b9a705a2fbbfac79db739e1f36cfca7aeb0a885aaf8b3efad98443

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page