How to Test a Function with Input Call

How to test a function with input call?

You should probably mock the built-in input function, you can use the teardown functionality provided by pytest to revert back to the original input function after each test.

import module  # The module which contains the call to input

class TestClass:

def test_function_1(self):
# Override the Python built-in input method
module.input = lambda: 'some_input'
# Call the function you would like to test (which uses input)
output = module.function()
assert output == 'expected_output'

def test_function_2(self):
module.input = lambda: 'some_other_input'
output = module.function()
assert output == 'another_expected_output'

def teardown_method(self, method):
# This method is being called after each test case, and it will revert input back to original function
module.input = input

A more elegant solution would be to use the mock module together with a with statement. This way you don't need to use teardown and the patched method will only live within the with scope.

import mock
import module

def test_function():
with mock.patch.object(__builtins__, 'input', lambda: 'some_input'):
assert module.function() == 'expected_output'

Pytest: How to test a separate function with input call?

Your problem has nothing to do with moving the input to a separate function, or even with monkeypatching; it has to do with passing the wrong number of arguments—just as the error message says.

In the example you refer to, the monkeypatching function is defined to take one parameter, and the input call passes one argument.

If your own attempt, the monkeypatching function is defined to take one parameter, but the input call passes no arguments.

You can just define it to take an optional parameter, just like the real input:

m.setattr('builtins.input', lambda prompt="": ans)

How to test Input with React Testing Library?

Your tested component is a controlled component : it receives (props) its value from the parent component, with a function reference which notifies the parent that the user changed the input value. Typically this function will update the parent state, which is passed down to the child component, and used as the input value.

In your test you only render the child component, and you mock the callback function. So you cannot expect the input value to change when triggering user interactions in your test. You can only test that the title props is used as value for the input, and that the callback function (which is mocked in your test) is correctly called when you trigger user interactions. But you cannot test a "full scenario" without rendering the parent component.

test("input value is the title props", async () => {
renderComponent("test");
const input = await screen.findByRole("textbox", { name: /search/i });
await waitFor(() => expect(input).toHaveValue("test"));
});

test("callback function is called on user interactions", async () => {
renderComponent("test");
const input = await screen.findByRole("textbox", { name: /search/i });
userEvent.type(input, "new value");
expect(mockedOnChange).toHaveBeenCalledWith("new value");
});

How to test function, that has two or more input()'s inside?

Here is my solution:

class SimulatedInput:

def __init__(self,*args):
self.args = iter(args)

def __call__(self,x):
try:
return next(self.args)
except StopIteration:
raise Exception("No more input")

Then you could use it like you did before:

def test_some_function(self):
codefile.input = SimulatedInput("u","v")
codefile.some_function() . . . .

How to test interactive python script with multiple `input` functions

You can use side_effect for this. Side_effect takes a list as input and provides you the result in the order of elements.

Assuming you have the test and source code in separate directories

@patch('sample.input')
def test_options(mock_input):
mock_input.side_effect = ['y', 'y']
result = unsubscribe()
assert result == "your discount code is SAVE20, and we are glad you have you back"

You can take this to the next step by defining the exact output you want for your use case, instead of arbitrarily passing yes and no values

@patch('sample.input')
def test_options(mock_input):

def input_side_effect(*args, **kwargs):
m = {
'are you unsubscribing? [y/n]': 'y',
'would you like a 20%% off discount code? [y/n]': 'y',
}.get(args[0])
if m:
return m
pytest.fail('This question is not expected')

mock_input.side_effect = input_side_effect
result = unsubscribe()
assert result == "your discount code is SAVE20, and we are glad you have you back"


Related Topics



Leave a reply



Submit