Tuesday, 14 September 2021

Python Testing: How to test correct function calls of downstream functions?

TLDR: Upstream function is called with wrong argument order. How do I ensure, this is caught by tests?

Here is a minimal example of my setup:

# functions.py

def inner(age, name):
    if age > 18:
        return f'{name} is an adult.'
    else: 
        return f'{name} is a child.'

def outer(name, age):
    info = inner(name, age)
    return f'This is {name}. {info}'


# tests.py

from functions import inner, outer
from unittest.mock import Mock, patch

def test_inner():
    name, age = "John", 43
    info = inner(age, name)
    expected = "John is an adult."
    assert info == expected

def test_outer():
    name, age = "John", 43

    mock_get_info = Mock()
    mock_get_info.return_value = "Info"
    patch_get_info = patch("functions.inner", new=mock_get_info)

    with patch_get_info:
        info = outer(name, age)
        expected = 'This is John. Info'
        assert info == expected
        mock_get_info.assert_called_once_with(name, age)

Functionality:

  • Two functions and their corresponding tests.
  • The inner function produces a string which is checked for correctness by the test_inner function.
  • The outer function calls the inner function and concatenates it to it's own string. The correct concatenation and inner function call are checked by the test_outer function.
  • Additionally, apart from this minimal example, the inner function may produce a very large string which I don't want to check explicitly in the test_outer which is why the inner return value is mocked.

You may have noticed, that the outer function actually passes the arguments to the inner function the wrong way around. This is because I could have decided to change the order of arguments of the inner function and changed the test_inner accordingly, but forgot that the outer function calls the inner function. This is not caught by the test_outer, because it is internally consistent. We only find out in production, that the inner function throws an error.

How do I ensure, that all tests of downstream functions catch modified function definitions?



from Python Testing: How to test correct function calls of downstream functions?

No comments:

Post a Comment