CoolTarka
CoolTarka

Reputation: 113

How can I test a loop with multiple input calls?

I'm trying to test a fuction that dependets a of multiple user inputs to return some value.

I've already looked for multiples unswers here but none was able to resolve my problem. I saw things with parametrize, mock and monkey patch but none helped. I think a lot is because I don't clearly understood the concepts behind what was being done and I couldn't adapt to my problem. I saw suggestion of using external file for this but I don't wont to depend on that. I'm trying with pytest and python 3.7.3

The function that I want to test is something like this

def function():
    usr_input = input('please enter a number: ')
    while True:
        if int(usr_input) < 5:
            usr_input = input('please, enter a value less then 5: ')
        else:
            break
    return usr_input

I want to know how can I pass two input values to test the function when the inserted value is not valid. Example: Send value 6 and 2, make an assert expecting value 2 and pass the test. My others tests look like this:

def test_input(monkeypatch):
    monkeypatch.setattr('builtins.input', lambda x: 6)
    test = function()
    assert test == 2

but, for this case, they loop. It's possible to do this only with parametrize or other simple code?

EDIT

I added a int() in my "if", as wim pointed in the accepted answer, just to prevent any confusion for future readers. I'm assuming the cast is possible.

Upvotes: 6

Views: 1640

Answers (1)

wim
wim

Reputation: 362716

Two problems here, you need to convert the input into a number otherwise the comparison will fail, comparing a string with a number: usr_input < 5. Note that the real input will never return a number, only a string.

Once you've cleared that up, you can monkeypatch input with a callable that can return different values when called:

def fake_input(the_prompt):
    prompt_to_return_val = {
        'please enter a number: ': '6',
        'please, enter a value less then 5: ': '2',
    }
    val = prompt_to_return_val[the_prompt]
    return val

def test_input(monkeypatch):
    monkeypatch.setattr('builtins.input', fake_input)
    test = function()
    assert test == 2

If you install the plugin pytest-mock, you can do this more easily with the mock API:

def test_input(mocker):
    mocker.patch('builtins.input', side_effect=["6", "2"])
    test = function()
    assert test == 2

Upvotes: 5

Related Questions