Search code examples
pythonrecursionpython-unittest

How can I unit test a recursive functions in python?


I was wondering how can I unit test if a recursive function has been called correctly. For example this function:

def test01(number):
        if(len(number) == 1):
            return 1
        else:
            return 1+test01(number[1:])

It counts recursvely how many digits a number has (assuming the number type is string) So, I want to test if the function test01 has been called recursively. It would be ok if it is implemented just like that, but not if it is implemented as:

def test01(number):
    return len(number)

EDIT: The recursive approach is mandatory for educational purposes, so the UnitTest process will automate programming exercises checking. Is there a way to check if the function was called more than once? If that is possible, I can have 2 tests, one asserting the correct output and one to check if the function was called more than once for the same input.

Thank you in advance for your help


Solution

  • Guessing by the tags I assume you want to use unittest to test for the recursive call. Here is an example for such a check:

    from unittest import TestCase
    import my_module
    
    class RecursionTest(TestCase):
        def setUp(self):
            self.counter = 0  # counts the number of calls
    
        def checked_fct(self, fct):  # wrapper function that increases a counter on each call
            def wrapped(*args, **kwargs):
                self.counter += 1
                return fct(*args, **kwargs)
    
            return wrapped
    
        def test_recursion(self):
            # replace your function with the checked version
            with mock.patch('my_module.test01',
                            self.checked_fct(my_module.test01)):  # assuming test01 lives in my_module.py
                result = my_module.test01('444')  # call the function
                self.assertEqual(result, 3)  # check for the correct result
                self.assertGreater(self.counter, 1)  # ensure the function has been called more than once
    

    Note: I used import my_module instead of from my_module import test01 so that the first call is also mocked - otherwise the number of calls would be one too low.

    Depending on how your setup looks like, you may add further tests manually, or auto-generate the test code for each test, or use parametrization with pytest, or do something else to automate the tests.