skip to Main Content

`

def conversion():
    options = print('Would you like to convert hours to mins, or mins to hours?')
    choice = input()

    if choice == 'hours to mins':
        hours = int(input('How many hours? '))
        mins = hours * 60
        print(mins, 'Minutes')
    elif choice == 'mins to hours':
        mins = int(input('How many minutes? '))
        hours = mins/60
        print(hours, 'Hours')
    else:
        print('An error has occured')
        


conversion()

This is the production code which is meant to be used to write a corresponding test code. `

I am unsure on how to go about writing a test code using ‘siminput’ ‘assert’ and the a variable ‘actual’ to write a working test code for the line of code above for it to properly run in unittest.

2

Answers


  1. You can use pytest with the pytest-mock extension. Install them via pip or conda, or whatever you use.


    Quick Fix

    First I made a small change to your code to make it a bit easier to test: I added a return statement. Now the code will also return the result.

    # conversion.py
    def conversion():
        print('Would you like to convert hours to mins, or mins to hours?')
        choice = input()
    
        if choice == 'hours to mins':
            hours = int(input('How many hours? '))
            mins = hours * 60
            print(mins, 'Minutes')
            return mins
        elif choice == 'mins to hours':
            mins = int(input('How many minutes? '))
            hours = mins/60
            print(hours, 'Hours')
            return hours
        else:
            print('An error has occured')
            return False
    

    Ok, now we create a test

    # conversion_test.py
    def test_hrs_to_min(mocker):
        input_provider = mocker.patch('builtins.input')
        # The following line is crucial: You configure the 
        # values each call to `Input` will return in order. 
        input_provider.side_effect = ['hours to mins', '3']
        result = conversion()
        assert result == 3*60
    

    when we run this now with pytest -s from the command line, we see the expected print result and a green dot for the passed test. Try to add the other scenarios and error cases on your own (e.g. what happens if hour input is not an int)

    You can also mock the builtin.print and check if it was called with the right arguments (mock_print.assert_called_with(3*60, "Minutes").

    See Mocking examples for further details.


    Better Solution

    As already mentioned it’d be a good idea to separate concerns in your code.

    def conversion():
        print('Would you like to convert hours to mins, or mins to hours?')
        choice = input()
        if choice == 'hours to mins':
            hours = int(input('How many hours? '))
            print(hrs2mins(hours), 'Minutes')
        elif choice == 'mins to hours':
            mins = int(input('How many minutes? '))
            print(min2hrs(mins), 'Hours')
    
        print('An error has occurred')
        return False
    
    
    def hrs2mins(hrs: int) -> int:
        return hrs * 60
    
    
    def min2hrs(mins: int) -> float:
        return mins/60
    

    now you can test the "business logic" (the conversion) separately from the User interface…

    Login or Signup to reply.
  2. test_input.py:

    def conversion():
        print("Would you like to conver...")
        choice = input()
    
        if choice == 'hour to mins':
            hours = int(input("How many hours?"))
            mins = hours * 60
            print(mins, "Minutes")
        else:
            print('An error has occured')
    

    test_conversion.py:

    from unittest import mock
    from unittest import TestCase
    from test_input import conversion
    from io import StringIO
    
    
    class ConversionTest(TestCase):
        @mock.patch('test_input.input', create=True)
        def test_minutes(self, mocked_input):
            mocked_input.side_effect = ["hour to mins", 4]
            with mock.patch('sys.stdout', new=StringIO()) as fake_out:
                conversion()
                output = fake_out.getvalue()
                self.assertEqual(output.replace("n", ""), 'Would you like to conver...240 Minutes')
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search