Search code examples
pythontestingwhile-loopinfinite-loop

Infinite loop testing


How could I test an infinite loop? For example:

func.py

def func():
    while True:
        char = input().lower()
        if char == 'q':
            break 
        elif char.isalpha():
            print("It's not a number")
        if int(char) == #some_number
            break
        else:
            print('Try again')
        

test.py

def test_func():
    ???

Is there any solution for testing this?


Solution

  • You can use unittest to mock the user's input:

    import builtins
    from unittest.mock import patch
    
    def func():
        while True:
            char = input().lower()
            if char == 'q':
                break 
            elif char.isalpha():
                print("It's not a number")
            if int(char) == 3:
                break
            else:
                print('Try again')
    
    def test_func(inputs):
        with patch("builtins.input") as input_mock:
            input_mock.side_effect = inputs
            func()
    
    test_func(["q"])
    test_func(["3"])  
    test_func(["4", "5", "6"])  # StopIteration error indicates this input is not sufficient for the function to return
    test_func(["a", "b", "c", "q"])  # ValueError indicates a bug in the function
    test_func(["4", "5", "6", "q"])  # Try again 3 times as expected
    

    EDIT: You could also use unittest to capture the printed output and return it, so that you can check this output systematically against the expected output.

    import builtins
    from unittest.mock import patch
    import io
    
    def test_func(inputs):
        with patch("builtins.input") as input_mock, \
             patch("sys.stdout", new_callable=io.StringIO) as output_mock:
            input_mock.side_effect = inputs
            try:
                func()
            except StopIteration:
                print("FUNCTION DID NOT RETURN")
            return output_mock.getvalue().strip().split("\n")
    
    print(test_func(["q"]) == [""]) # True
    print(test_func(["4", "5", "6", "q"]) == ['Try again', 'Try again', 'Try again']) # True