0

I would like to simulate inputs from the user in unittest using Python 3.8. I have a function that first asks the user which program to execute and then multiple other inputs to get the required values for the said app. I would like to simulate these inputs (input()) in unittest. I was unable to find an answer from this post, as that answer uses "inputted" text and then plugs it into a function, and does not work seamlessly with input(). I would like a solution that works seamlessly with input(), as if a human was running the program, and returns the values that the function in the program outputs. Using separate functions is very tedious and would mean updating the program twice, which is not ideal. If it the only way, I am willing to deal with it, but I would prefer not to. Here is some code that will need to be tested.

main.py:

import numworksLibs

def page1():
    if (prgrmchoice == "1"):
        numer = int(input("Enter the Numerator of the Fraction: "))
        denom = int(input("Enter the Denominator of the Fraction: "))
        numworksLibs.simplify_fraction(numer, denom)

And the library file takes this input and spits out an answer (numworksLibs.py).

MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46
Revvz
  • 455
  • 1
  • 6
  • 14
  • You may check the other answers in the question you mentioned - only the first answer uses a separate function. – MrBean Bremen Sep 24 '20 at 17:22
  • You'll probably have to use some patch decorator, like [this answer explains](https://stackoverflow.com/a/21047132/7447711). I would definitely argue that you should split the function though. Lots of things can go wrong with keyboard IO, and writing unit tests for a function that receives just strings is gonna be way more straightforward and effective than a function that obtains user input _and_ process it. – Mikael Sep 24 '20 at 17:27
  • @Mikael I'll definitely think about this. Thanks for your input. – Revvz Sep 24 '20 at 18:14
  • @MrBeanBremen The others weren't much help, but I'll try and adapt the program to fit the other answer like Mikael mentioned. – Revvz Sep 24 '20 at 18:15
  • Check also [this answer](https://stackoverflow.com/a/61373960/12480730) I gave to a somewhat related question recently. Generally, it always helps to show some [minimal code](https://stackoverflow.com/help/minimal-reproducible-example), so we could give more concrete help. – MrBean Bremen Sep 24 '20 at 18:23
  • @MrBeanBremen I added some code. – Revvz Sep 24 '20 at 19:41
  • I thought of another approach. Instead of using the main file, I could use the library for testing. It accepts the same strings as the main file. If I have a return in the library function, would it also return to the test (outputs a test result)? – Revvz Sep 24 '20 at 19:43

1 Answers1

0

I'm not sure what exactly you want to test (maybe the output that numworksLibs generates), but as this is about mocking the input, I'll show a simplified example that does not use unknown variables or functions:

main.py

def page1():
    number = int(input("Enter the Numerator of the Fraction: "))
    denom = int(input("Enter the Denominator of the Fraction: "))
    return number, denom

test_main.py

from unittest import mock
from main import page1

@mock.patch("main.input")
def test_input(mocked_input):
    mocked_input.side_effect = ['20', '10']
    assert page1() == (20, 10)

You can put as many input values into the side_effect array as you want - this will simulate the return values of separate calls to input. You have to adapt your test code to your real code, of course.

This assumes pytest, for unittest it would look the same accept for the added self parameter.

MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46