Ishan Srivastava
Ishan Srivastava

Reputation: 1189

python pytest occasionally fails with OSError: reading from stdin while output is captured

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?

Upvotes: 20

Views: 29122

Answers (6)

Vicky
Vicky

Reputation: 1

You could also trigger this error if you have a main() (or similar) function in your code that calls the function(s) you're trying to test with pytest in your test file, but did not set a condition like this to call the main() function. For example:

if __name__ == "__main__":
    main()

Upvotes: 0

TheDronist
TheDronist

Reputation: 78

This can also occur if you moved a function or method that uses input() to another module and have no updated the module string in the patch decorator.

Upvotes: 0

wim
wim

Reputation: 362786

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 prompt="", /: "no")
    val = prompt_to_activate(bear=..., printer=...)
    assert not val

Upvotes: 12

learningshark
learningshark

Reputation: 11

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()

Upvotes: 0

Joshua Cook
Joshua Cook

Reputation: 13435

You might also receive this if you set a breakpoint, but didn't use the -s flag with pytest.

Upvotes: 15

Tom Bug
Tom Bug

Reputation: 329

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.

Upvotes: 5

Related Questions