Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 616
CoolTarka Avatar asked Jun 07 '19 16:06

CoolTarka


People also ask

How to take multiple inputs in python using while loop?

Simple example codes Multiple Inputs with Python using While Loop. Exit the loop if the user enters “stop”. Take multiple inputs and append them to the list. If you use an infinite loop then break it if the input is 0.


1 Answers

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
like image 164
wim Avatar answered Oct 16 '22 21:10

wim