python pytest occasionally fails with OSError: reading from stdin while output is captured
Question:
While running a particular unittest
with pytest
, it occasionally fails with this error (mentioned in the title) and from the stack trace it happens on the line
choice = input().lower()
when the control reaches this statement, the entire function is:
def prompt_to_activate(bear, printer):
PROMPT_TO_ACTIVATE_STR = ('program has found {} to be useful '
'based of dependencies discovered from your '
'project files. n Would you like to activate '
'it? (y/n)')
printer.print(PROMPT_TO_ACTIVATE_STR)
choice = input().lower()
if choice.startswith('y'):
return True
elif choice.startswith('n'):
return False
else:
return prompt_to_activate(bear, printer)
for i in range(0, 3):
a = i
print(a)
I tried adding some time.sleep(x)
before that statement but that wouldn’t fix it. Can somebody tell me the exact reason why this is happening and how to fix it?
Answers:
Since input()
is an interactive function, you’ll want to mock out the return value in your automated tests. Something like this:
def test_prompt(capsys, monkeypatch):
monkeypatch.setattr('path.to.yourmodule.input', lambda: 'no')
val = prompt_to_activate(bear=..., printer=...)
assert not val
In case someone else stumbles upon this, this error will also be raised if you forgot a pdb breakpoint (import ipdb; ipdb.set_trace()
) in your code.
You might also receive this if you set a breakpoint, but didn’t use the -s
flag with pytest.
I also had the same problem and figured it out after learning more unit testing and mocking! Adding to @wim’s answer… Another way to mock input is:
@mock.patch("my_module.input")
def test_my_actual_func(self, mock_input):
my_actual_func()
While running a particular unittest
with pytest
, it occasionally fails with this error (mentioned in the title) and from the stack trace it happens on the line
choice = input().lower()
when the control reaches this statement, the entire function is:
def prompt_to_activate(bear, printer):
PROMPT_TO_ACTIVATE_STR = ('program has found {} to be useful '
'based of dependencies discovered from your '
'project files. n Would you like to activate '
'it? (y/n)')
printer.print(PROMPT_TO_ACTIVATE_STR)
choice = input().lower()
if choice.startswith('y'):
return True
elif choice.startswith('n'):
return False
else:
return prompt_to_activate(bear, printer)
for i in range(0, 3):
a = i
print(a)
I tried adding some time.sleep(x)
before that statement but that wouldn’t fix it. Can somebody tell me the exact reason why this is happening and how to fix it?
Since input()
is an interactive function, you’ll want to mock out the return value in your automated tests. Something like this:
def test_prompt(capsys, monkeypatch):
monkeypatch.setattr('path.to.yourmodule.input', lambda: 'no')
val = prompt_to_activate(bear=..., printer=...)
assert not val
In case someone else stumbles upon this, this error will also be raised if you forgot a pdb breakpoint (import ipdb; ipdb.set_trace()
) in your code.
You might also receive this if you set a breakpoint, but didn’t use the -s
flag with pytest.
I also had the same problem and figured it out after learning more unit testing and mocking! Adding to @wim’s answer… Another way to mock input is:
@mock.patch("my_module.input")
def test_my_actual_func(self, mock_input):
my_actual_func()