Max Fesenko
Max Fesenko

Reputation: 143

Python mock launches whole program instead of substituting input to specific method

I have a program, like:

module "Main":

import SymbolCalculator as sc


# Defining constants:
TEXT_INTRO = sc.TEXT_INTRO
TEXT_INVITE = "Please print any sentence below:\n"
sentence = ""
# Printing introduction to the program:
print TEXT_INTRO

def getting_result():
    # Getting input string from console
    sentence = sc.get_input_from_prompt(TEXT_INVITE)
    # Forming result list via methods defined in SymbolCalculator module
    return sc.characters_calculator(sentence)
result_list = getting_result()
# Computing summary via method defined in SymbolCalculator module
sc.printing_summary(sentence, result_list)
# Printing tuples with characters and their occurrences raw-by-raw
sc.printing_list(result_list)
raw_input("Please press any button to quit the program.")
print 'Bye!!!'

And I'm trying to create a simple unit test with mocked raw_input (updated):

from unittest import TestCase, main
from mock import patch
from Ex_41_42_SymbolCalculatorMain import getting_result


class Ex_4a1_SymbolCalculatorUnitTestWMock(TestCase):
    #@patch ('Ex_41_42_SymbolCalculator.get_input_from_prompt', return_value = 'aabc')
    def test_valid_input(self):
        with patch('__builtin__.raw_input', return_value = 'aaabbc') as _raw_input:
            self.assertEqual(getting_result(), [('a', 3), ('b', 2), ('c', 1)])
            _raw_input.assert_called_once_with('Please print any sentence below:\n')

    @patch ('Ex_41_42_SymbolCalculator.get_input_from_prompt', return_value = '')
    def test_empty_input(self, mock):
        self.assertEqual(getting_result(), [])

if __name__ == "__main__":
    main()

As well I tried to go via decoration of the tested method by itself, like:

...
@patch ('Ex_41_42_SymbolCalculator.get_input_from_prompt', return_value = 'aabc')
...

My problem is that when I launch the test, all the "Main" module runs at the moment of getting_result method calling. So it starts from the very beginning, asks me to make an input via command prompt, etc. Thus not only test, but the whole regular program is running.

While I'm expecting that only getting_result method is called being provided with return_value.

Please advise.

Upvotes: 0

Views: 30

Answers (1)

BrenBarn
BrenBarn

Reputation: 251408

When you import a module, all the code in the module is run. It doesn't matter that you used from Ex_41_42_SymbolCalculatorMain import getting_result instead of import Ex_41_42_SymbolCalculatorMain; you're still importing the module. There's no way to just "get" one function without executing the rest of the code in the module.

Instead, you should put that code in a function, and then call it from within an if __name__ == "__main__" block, like this:

def getting_result():
    # Getting input string from console
    sentence = sc.get_input_from_prompt(TEXT_INVITE)
    # Forming result list via methods defined in SymbolCalculator module
    return sc.characters_calculator(sentence)

def do_stuff():
    print TEXT_INTRO
    result_list = getting_result()
    # Computing summary via method defined in SymbolCalculator module
    sc.printing_summary(sentence, result_list)
    # Printing tuples with characters and their occurrences raw-by-raw
    sc.printing_list(result_list)
    raw_input("Please press any button to quit the program.")
    print 'Bye!!!'

if __name__ == "__main__":
    do_stuff()

Then do_stuff() will only be run if you execute that file directly, not if you import it. This will allow you to import the module without running the stuff in do_stuff. You can learn more about the __main__ business by searching this site for zillions of questions about it (such as this one).

Upvotes: 1

Related Questions