如何对函数内部进行的函数调用序列进行单元测试 [python]
How to unittest the sequence of function calls made insde a fuction [python]
我想对一个函数进行单元测试,并断言函数调用的顺序是否在函数 workflow() 内进行。
像,
[1st called] fetch_yeargroup_ls()
[2nd called] invoke_get_links().......
我搜索了许多讨论,但从未找到回答我问题的人。
在我看来,测试或特别是 TDD 的真正目的是设计更好的代码。如果为您的代码编写测试变得困难,则表明您的代码是高度耦合的,您需要对其进行重构。此外,编写断言函数顺序的测试会使测试与代码过于耦合并且非常脆弱。
话虽如此,您还是可以测试订单,虽然有点老套。比如说,您有两个名为 func_a
和 func_b
的函数,您希望确保 func_a
在 func_b
之前被调用。将 func_a
替换为 returns 一些随机值的模拟,以便它停止执行进一步发生。还要模拟 func_b
,并确保调用 func_a
并且不调用 func_b
。您也需要对其他排列执行此操作。
如果您正在使用 mock
,您可以在修补这些函数时将模拟创建为父模拟的属性:
try:
# Python 3
from unittest.mock import MagicMock, patch, call
except ImportError:
# Python 2, install from PyPI first
from mock import MagicMock, patch, call
import unittest
from module_under_test import function_under_test
class TestCallOrder(unittest.TestCase):
def test_call_order(self):
source_mock = MagicMock()
with patch('module_under_test.function1', source_mock.function1), \
patch('module_under_test.function2', source_mock.function2), \
patch('module_under_test.function3', source_mock.function3)
# the test is successful if the 3 functions are called in this
# specific order with these specific arguments:
expected = [
call.function1('foo'),
call.function2('bar'),
call.function3('baz')
]
# run your code-under-test
function_under_test()
self.assertEqual(source_mock.mock_calls, expected)
因为这 3 个函数附加到 source_mock
,所以对它们的所有调用都记录在 Mock.mock_calls
属性中的父模拟对象上,您可以对它们的调用顺序进行断言。
我只是通过在 source_mock
对象上查找它们作为属性来附加 3 个函数模拟,但您也可以使用 Mock.attach_mock()
method 将您以不同方式创建的模拟附加到父对象.
我想对一个函数进行单元测试,并断言函数调用的顺序是否在函数 workflow() 内进行。 像,
[1st called] fetch_yeargroup_ls()
[2nd called] invoke_get_links().......
我搜索了许多讨论,但从未找到回答我问题的人。
在我看来,测试或特别是 TDD 的真正目的是设计更好的代码。如果为您的代码编写测试变得困难,则表明您的代码是高度耦合的,您需要对其进行重构。此外,编写断言函数顺序的测试会使测试与代码过于耦合并且非常脆弱。
话虽如此,您还是可以测试订单,虽然有点老套。比如说,您有两个名为 func_a
和 func_b
的函数,您希望确保 func_a
在 func_b
之前被调用。将 func_a
替换为 returns 一些随机值的模拟,以便它停止执行进一步发生。还要模拟 func_b
,并确保调用 func_a
并且不调用 func_b
。您也需要对其他排列执行此操作。
如果您正在使用 mock
,您可以在修补这些函数时将模拟创建为父模拟的属性:
try:
# Python 3
from unittest.mock import MagicMock, patch, call
except ImportError:
# Python 2, install from PyPI first
from mock import MagicMock, patch, call
import unittest
from module_under_test import function_under_test
class TestCallOrder(unittest.TestCase):
def test_call_order(self):
source_mock = MagicMock()
with patch('module_under_test.function1', source_mock.function1), \
patch('module_under_test.function2', source_mock.function2), \
patch('module_under_test.function3', source_mock.function3)
# the test is successful if the 3 functions are called in this
# specific order with these specific arguments:
expected = [
call.function1('foo'),
call.function2('bar'),
call.function3('baz')
]
# run your code-under-test
function_under_test()
self.assertEqual(source_mock.mock_calls, expected)
因为这 3 个函数附加到 source_mock
,所以对它们的所有调用都记录在 Mock.mock_calls
属性中的父模拟对象上,您可以对它们的调用顺序进行断言。
我只是通过在 source_mock
对象上查找它们作为属性来附加 3 个函数模拟,但您也可以使用 Mock.attach_mock()
method 将您以不同方式创建的模拟附加到父对象.