Home > front end >  How can i create a unit test for a function that asks user for input
How can i create a unit test for a function that asks user for input

Time:09-21

I'm new to unit testing. I'm working on an ATM program. I want to make a unit test for the deposit operation. I have checked online but i am not getting an answer to my problem. This is my first time of posting here. Thank you for the assistance in advance

This is my code below

def deposit_operation(user):

    amount_to_deposit = int(input('ENTER AMOUNT YOU WANT TO DEPOSIT: ')
    # amount should be in multiples of 1,000
    if amount_to_deposit % 1000 != 0:
        print('AMOUNT YOU WANT TO DEPOSIT MUST BE IN MULTIPLES OF 1000 NAIRA NOTES')
        deposit_operation(user)
    else:
        user[4] = user[4]   amount_to_deposit
        print(f'*** YOUR NEW BALANCE IS: {user[4]} NAIRA ****')

        perform_another_operation(user)

CodePudding user response:

You separate out the parts that do I/O like take user input from the parts that do operations on the input.

def get_user_input():
    user_input = input("Enter the amount to deposit: ")
    data = validate_user_input(user_input)
    if data:
        return data
    else:
        print("Input must be a number that is a multiple of 1000")
        return get_user_input()

def validate_user_input(value):
    try:
        parsed = int(user_input)
        if parsed % 1000 == 0:
            return parsed
        else:
            return False
    except:
        return False

def update_account(user, amount):
    user[4] = user[4]   amount
    return user

if __name__ == "__main__":
    user = ...
    update_account(user, get_user_input())

Now you can test the validation logic and the account update logic independently and you don't need to test get_user_input at all. No complicated mocking, just good decomposition.

from unittest import TestCase

class TestAtm(TestCase):

    def test_validate_user_input(self):
        assert(validate_user_input("1") is False)
        assert(validate_user_input("1000") is True)
        assert(validate_user_input("pizza") is False)
        # and so on...

    def test_update_amount(self):
        # Test that acct gets updated

Also, please don't use lists to store positional data like that. Use a dictionary or a namedtuple or a dataclass or an actual user class. Trying to remember that the 5th index is the account value is asking for bugs.

CodePudding user response:

Something like:

test_deposit_operation.py

import mock
from unittest import TestCase
import builtins
# define user equal to [1,2,3,4,5]
def deposit_operation(user=[1,2,3,4,5]):
    amount_to_deposit = int(input('ENTER AMOUNT YOU WANT TO DEPOSIT: '))
    
    # amount should be in multiples of 1,000
    if amount_to_deposit % 1000 != 0:
        return('AMOUNT YOU WANT TO DEPOSIT MUST BE IN MULTIPLES OF 1000 NAIRA NOTES')
    else:
        user[4] = user[4]   amount_to_deposit
        return(f'*** YOUR NEW BALANCE IS: {user[4]} NAIRA **** ')
        
        
        #perform_another_operation(user)
        

class Test(TestCase):

    def test_deposit_operation_divide_by_1000_not_equel_zero(self):
        with mock.patch.object(builtins, 'input', lambda _: 10001):
            self.assertEqual(deposit_operation(), 'AMOUNT YOU WANT TO DEPOSIT MUST BE IN MULTIPLES OF 1000 NAIRA NOTES')

   
    def test_deposit_operation_divide_by_1000_equel_zero(self ):
        with mock.patch.object(builtins, 'input', lambda _: 1000):
            self.assertEqual(deposit_operation(), '*** YOUR NEW BALANCE IS: 1005 NAIRA **** ')

then:

pytest test_deposit_operation.py
  • Related