0

I'm fairly new to unit test in Python, but have done a few so I understand the basics of it. One problem I'm having is being able to mock input and then test for the STDOUT based on that mocked input. I tried the solution in this post: python mocking raw input in unittests but didn't find any success with the given method. My test seems like it's getting hung up when asking for the input. I want to be able to mock the input for the Run module and then be able to test for the STDOUT which can be either True/False Here is my Run code

#imports
import random

def main():
    #variables
    dolphins = random.randrange(1,11)

    guess = int(input("This is a prompt"))

    print(guess == dolphins)

Really simple here. Here is my Testsuite

import unittest
from unittest.mock import patch

from Run import *

class GetInputTest(unittest.TestCase):

  @patch('builtins.input', return_value=1)
  def test_answer_false(self, input):
    self.assertEqual(main(), 'False')


if __name__ == "__main__":
  unittest.main()

So here I am feeding the input a value of 1 and then call the main() during my assertion and expect a value of False but it doesn't even get that far, the program just continuously runs, I think because it's waiting for an input and I may not be mocking it correctly. I also tried feeding builtins.input into the @patch parameter and I get the same result.

There's no error messages or tracebacks. Hopefully someone with a little more experience can tell me what I am doing wrong. Thank you all in advance for helping me out.

Community
  • 1
  • 1
salce
  • 409
  • 1
  • 12
  • 28

1 Answers1

0

You can make your main as a function that takes arguments instead.

def main(args):
    ...do stuff

if __name__ == '__main__':
    args = input('Get input')
    main(args)

Then just unittest it as a normal function.

class TestMain(unittest.TestCase):
    def testmain(self):
        self.assertTrue(main(5), 'foo')

If you still want to have the input within your main, then you need to mock patch input not main.

postelrich
  • 3,274
  • 5
  • 38
  • 65
  • So I would need `builtins.input` instead of main? because I still want to call input within the `main` – salce Sep 09 '15 at 20:31
  • You would need to do `@patch('input', return_value)` instead. I'm assuming you're using patch correctly but try it out. – postelrich Sep 09 '15 at 20:40
  • So I updated my code patching the input. I couldn't just put `input` I had to add `builtins` as well. This gives me the following assertion error `AssertionError: None != 'False` I assumed it's because the `main()` wasn't getting called in the `Run` module. So I called it and I still have that issue where it gets hung up. Any insight here? – salce Sep 09 '15 at 20:47
  • I tried that as well, I had this line before `return print(guess==dolphins)` but the testsuite still gets hung up and doesn't run the test fully. It seems like it waiting for the input, but not taking the one I patched. – salce Sep 09 '15 at 20:54
  • i think figuring out what's wrong with that on your own will be a good learning experience. – postelrich Sep 09 '15 at 20:56
  • Don't forget to mark the answer as correct, and feel free to ask a separate question if you're still stuck on your bug, though you should be able to get it. – postelrich Sep 09 '15 at 21:08