I have a console program written in Python. It asks the user questions using the command:
some_input = input('Answer the question:', ...)
How would I test a function containing a call to input
using pytest
?
I wouldn't want to force a tester to input text many many times only to finish one test run.
You can do it with
mock.patch
as follows.First, in your code, create a dummy function for the calls to
input
:In your test functions:
For example if you have a loop checking that the only valid answers are in ['y', 'Y', 'n', 'N'] you can test that nothing happens when entering a different value instead.
As The Compiler suggested, pytest has a new monkeypatch fixture for this. A monkeypatch object can alter an attribute in a class or a value in a dictionary, and then restore its original value at the end of the test.
In this case, the built-in
input
function is a value of python's__builtins__
dictionary, so we can alter it like so:Edit: Changed
lambda: "Mark"
tolambda x: "Mark"
You can replace
sys.stdin
with some custom Text IO, like input from a file or an in-memory StringIO buffer:this is more robust than only patching
input()
, as that won't be sufficient if the module uses any other methods of consuming text from stdin.This can also be done quite elegantly with a custom context manager
And then just use it like this for example:
You should probably mock the built-in
input
function, you can use theteardown
functionality provided bypytest
to revert back to the originalinput
function after each test.A more elegant solution would be to use the
mock
module together with awith statement
. This way you don't need to use teardown and the patched method will only live within thewith
scope.