-
-
Notifications
You must be signed in to change notification settings - Fork 358
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
Easier use of recorder beta feature? #696
Comments
Hey ! Thanks @gswilcox01 for sharing your setup. I definitely agree that providing facilities and documenting how back and forths between record/activate is supposed to be done would help a lot in using this otherwise great library. Here I went one small step further and combined both decorators in a third one that conditionally switches between recorder and apply, based on a configuration (in my case a django setting but could just as well be an env var). I also added a import functools
import inspect
import pathlib
import responses
import responses._recorder
def make_filename(func):
module = inspect.getmodule(func)
# FIXME: include test case class name to avoid clashes
directory = pathlib.Path(module.__file__).parent.joinpath("_testing_results")
directory.mkdir(exist_ok=True)
return directory.joinpath(f"{func.__name__}.yaml")
def activate_responses():
def outer_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
with responses.RequestsMock() as rsp:
rsp._add_from_file(file_path=make_filename(func))
return func(*args, **kwargs)
return wrapper
return outer_decorator
def activate_recorder():
def outer_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
recorder = responses._recorder.Recorder()
with recorder:
try:
result = func(*args, **kwargs)
finally:
recorder.dump_to_file(
file_path=make_filename(func),
registered=recorder.get_registry().registered,
)
return result
return wrapper
return outer_decorator
def mock_responses(update_results=False):
"""Decorator to record then mock requests made with the requests module.
When update_results is True, will store requests to a yaml file. When it
is false, it will retrieve the results, allowing to run tests offline.
Usage:
import requests
from mdmodelpoc.testing.requests import mock_responses
from django.conf import settings
class MyTestCase(TestCase):
@mock_responses(update_results=settings.TESTS_UPDATE_STORED_RESULTS)
def test_mytest(self):
request.get("https://example.com)
...
"""
if update_results:
return activate_recorder()
else:
return activate_responses() |
Another aspect that would facilitate this workflow is handling domain that are environment dependent. It's very common to have code like def get_data():
# a service function that returns data
return requests.get(f"{os.environ['DATA_ENDPOINT']}/mydata.json") The issue is that this may not match the queries when run in different environments (e.g. I record requests in my local dev env to get test data from a local server, then want to retrieve responses in CI that has a different upstreams setting). I worked around this by adding an |
for now we are not planning to change the behavior |
I'm kind of a python noob. But I thought i'd see if you are interested in me contributing this back. Or maybe you could correct my understanding/show me what i missed.
I initially went down this path where i followed the docs/example to record/activate, and created a helper function to make a directory & calculate a filename based on the test name (1 file for each test):
It felt kind of annoying to have to repeat the test_name as a string (and make sure i don't copy/paste wrong), and also to comment/uncomment multiple lines to activate and load the file. So i made 2 simple decorators that did all of this for me.
My tests now look like this:
And for a single test_get.py module with 4 test functions in it, after recording i wind up with this "test_get_files" directory created & 4 output yaml files in it.
Code for the 2 new decorators is here if your are interested:
The text was updated successfully, but these errors were encountered: