Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a function with input call?

I have a console program written in Python. It asks the user questions using the command:

some_input = input('Answer the question:', ...) 

How would I test a function containing a call to input using pytest? I wouldn't want to force a tester to input text many many times only to finish one test run.

like image 657
Zelphir Kaltstahl Avatar asked Mar 07 '16 18:03

Zelphir Kaltstahl


People also ask

Can we use input in function?

If you want to number input or input in other data types, you need to perform type conversion on the input value. Let's understand this with an example. As you know whatever you enter as input, the input() function always converts it into a string. Read How to check if user input is a number or string.

Can you ask for input in a function Python?

To ask for user input in Python, use the built-in input() function. In addition to asking for simple string input like this, you also want to learn how to: Ask for multiple inputs in one go. Ask for input again until a valid input is given.

What is input () function give an example?

The input() function converts all the user input to a string even if that's the number. User can enter Unicode characters as well, as shown below.

What is input () function?

The input() function allows a user to insert a value into a program. input() returns a string value. You can convert the contents of an input using any data type.


2 Answers

As The Compiler suggested, pytest has a new monkeypatch fixture for this. A monkeypatch object can alter an attribute in a class or a value in a dictionary, and then restore its original value at the end of the test.

In this case, the built-in input function is a value of python's __builtins__ dictionary, so we can alter it like so:

def test_something_that_involves_user_input(monkeypatch):      # monkeypatch the "input" function, so that it returns "Mark".     # This simulates the user entering "Mark" in the terminal:     monkeypatch.setattr('builtins.input', lambda _: "Mark")      # go about using input() like you normally would:     i = input("What is your name?")     assert i == "Mark" 
like image 129
mareoraft Avatar answered Oct 01 '22 05:10

mareoraft


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' 
like image 31
Forge Avatar answered Oct 01 '22 03:10

Forge