Py.test inline object fix
I have a package:
- package/
- __init__.py
- cache.py
- module1.py
- module2.py
- tests/
- test_module1.py
- test_module2.py
- conftest.py
both module1
are module2
imported from cache.py
:
from package.cache import cache
@cache()
def foo():
...
by default, cache
uses file-based caching specified by dogpile.cache , however when running tests I would like to mock cache
with memory-based caching which is also supported by dogpile.cache .
that's what I'm doing:
# conftest.py
import pytest
@pytest.fixture(autouse=True)
def patch_cache(monkeypatch):
from dogpile.cache import make_region
m_cache = make_region().configure('dogpile.cache.memory')
monkeypatch.setattr('package.cache.cache', m_cache)
as you can see, I created a device in which using monkeypatch
to replace cache
withm_cache
however it doesn't work when i run the test with py.test
, they still use the old file based cache. something is wrong?
source to share
I recently had a similar issue with pytest and monkeypatching, which I thought should have been solved with monkeypatch
. I was trying to swap the cache in my flash app for on-board memory so my cached views and other stuff didn't accidentally destroy real app caches.
The problem I found is that, like so unittest.mock.patch
, I had to secure the place where the patch thing is imported and used, such as the site call.
Imagine the following set of modules:
# package1/app1/module1.py
from flask_app import cache
cache.get("SOMEKEY")
# package1/app2/module1.py
from flask_app import cache
cache.get("SOMEKEY")
# package1/app2/module2.py
from package1.app2.module1 import cache
cache.get("SOMEKEY")
Now, in pytest, to ensure that all these different versions cache
were monkeypatch
ed, I need a fixture that explicitly sets an attribute on all of them:
# conftest.py
from werkzeug.contrib.cache import SimpleCache
@pytest.fixture(scope="function", autouse=True)
def safe_cache(request, monkeypatch):
"""
Monkeypatch the cache so it doesn't clobber real keys.
Clear after every test.
"""
cache = SimpleCache()
monkeypatch.setattr('package1.app1.module1.cache', cache)
monkeypatch.setattr('package1.app2.module1.cache', cache)
monkeypatch.setattr('package1.app2.module2.cache', cache)
def teardown():
cache.clear()
request.addfinalizer(teardown)
return cache
This is annoying because every time I write a new module that imports the cache, I also have to render it harmless in the device that the monkey is transferring those caches to.
It works, however.
When I set a breakpoint in one of the modules importing the cache and check what it is using, I see the following:
ipdb> cache
<werkzeug.contrib.cache.SimpleCache object at 0x10d658ac8>
My flash app uses Redis cache, so seeing above shows it was successful.
source to share