mc92
mc92

Reputation: 495

Python unittest skip particular step in main application

I have a temperature application that takes user input (what units, temperature) to convert between different temperature units. It involves prompting the user for these units and numbers, through the normal str(input(xyz)) and float(input(123)) type of prompts, after which the rest of the application takes that data and uses it to perform the task, which from some basic manual testing I have found that it does correctly.

I wanted to practice writing unit tests for my application using unittest, and so wrote those too (correctly as well I believe). The tests pass where expected. My issue, however, is that even though I supply data that I will need for the test to work within the test itself, I am still taken through the input prompt in my my main application. While I can just press enter to skip through it and the tests will proceed as expected, I would rather find some way for either unittest to fill in those input prompts itself, bypass that input bit completely, or at least silence it so that I don't have to run through all my input prompts every time. Is it possible to do this with unittest?

Here is the basic structure of what I wrote for my main application

def main():
  unit_from, unit_to, temperature = user_input

  # continues with the rest of the application using above data...


#function to get user input
def user_input():
#gets user input using str and float prompts.
#and then returns those values for use in the rest of the program

main()

and for the unittests:

import unittest

#module containing classes where the formulas for conversion live
import temperature
#main application that utilzes temperature classes and drives it all
import temp_converter

class FahrenheitConvertTestCase(unittest.TestCase):
#one of my example tests
  def test_f_to_c(self):
    from_unit = 'FAHRENHEIT'
    to_unit = 'CELSIUS'
    temp = 32.0
    t_convert = temperature.Fahrenheit(temp, from_unit, to_unit)
    converted_temp = t_convert.convert()
    self.assertEqual(converted_temp, 0.0) 

Upvotes: 2

Views: 1614

Answers (2)

Andriy Ivaneyko
Andriy Ivaneyko

Reputation: 22021

You have to mock your input methods to return mocked value. See unittest.mock for reference of how to add mocking. Also consider reading Python common mock gotchas, it could save a lot of your time. So after adding mocking your test would look similar to code below:

@mock.patch('input', return_value='1')
def test_f_to_c(self, mock_input):
    from_unit = 'FAHRENHEIT'
    to_unit = 'CELSIUS'
    temp = 32.0
    t_convert = temperature.Fahrenheit(temp, from_unit, to_unit)
    converted_temp = t_convert.convert()
    self.assertEqual(converted_temp, 0.0) 

Good Luck !

Upvotes: 1

totoro
totoro

Reputation: 2456

When you have a module with a function call like

main()

it will be invoked on import of the module.

You can avoid that by wrapping it in the conditional

if __name__ == '__main__':
    main()

Then main will only be called when that module is executed as the main program, not on import.

Upvotes: 1

Related Questions