Pytest: Mock/monkey tinkering The built-in input() and print() functions in python… here is a solution to the problem.
Pytest: Mock/monkey tinkering The built-in input() and print() functions in python
How can I use Pytest monkey to patch the built-in input
and print
functions so that the output of other people’s code is captured and refactored with pytest
before?
For example, I got some code like this:
class QueryProcessor:
def __init__(self ...):
...
def write_search_result(self, was_found):
print('yes' if was_found else 'no')
def read_query(self):
return Query(input().split())
I don’t want
to read dozens of input parameters from stdin
, and I don’t want to print
out. I want to filter a directory full of mytest.in
and mytest.out
files using the function I wrote and pass input to pytest
using @pytest.mark.parametrize(...).
But I don’t know how to patch the clunky read
… and write...
functions in this class.
I suspect so:
@yptest.mark.parametrize("inputs..., expected outputs...", data_reading_func())
def test_QueryProcessor(monkeypatch, inputs..., expected outputs...):
"""Docstring
"""
q = QueryProcessor()
def my_replacement_read():
...
return [...]
def my_replacement_write():
...
return [...]
monkeypatch.???
assert ...
Can you help?
Thank you very much
Solution
While waiting for a reply, I thought of the following myself. I think the ideal answer is what I implemented as suggested by @hoefling – using patches
.
@pytest.mark.parametrize("m, n, commands, expec", helpers.get_external_inputs_outputs('spampath', helpers.read_spam_input_output))
def test_QueryProcessor(monkeypatch, m, n, commands, expec):
def mock_process_queries(cls):
for cmd in commands:
cls.process_query(Query(cmd.split())) # also mocks read_query()
def mock_write_search_result(cls, was_found):
outputs.append('yes' if was_found else 'no')
monkeypatch.setattr('test. QueryProcessor.process_queries', mock_process_queries)
monkeypatch.setattr('test. QueryProcessor.write_search_result', mock_write_search_result)
outputs = []
proc = QueryProcessor(m)
proc.process_queries()
assert outputs == expec
Update:
@pytest.mark.parametrize("m, n, commands, expec",
helpers.get_external_inputs_outputs(
'spampath',
helpers.read_input_output))
def test_QueryProcessor_mockpatch(m, n, commands, expec):
commands.insert(0,n)
mock_stdout = io. StringIO()
with patch('spammodule.input', side_effect=commands):
with patch('sys.stdout', mock_stdout):
proc = hash_chains. QueryProcessor(m)
proc.process_queries()
assert mock_stdout.getvalue().split('\n')[:-1] == expec