代码之家  ›  专栏  ›  技术社区  ›  Madhan Gokul

如何对函数〔python〕中的函数调用序列进行单元测试

  •  6
  • Madhan Gokul  · 技术社区  · 9 年前

    我想对一个函数进行单元测试,并断言在函数workflow()内进行的函数调用序列是否正确。 比如,

          [1st called] fetch_yeargroup_ls()
          [2nd called] invoke_get_links()....... 
    

    我搜索了许多讨论,但始终没有找到一个回答我的问题。

    2 回复  |  直到 9 年前
        1
  •  5
  •   Martijn Pieters    9 年前

    如果您正在使用 mock 在修补这些函数时,可以将mock创建为父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)
    

    因为这三个功能都附加到 source_mock ,对它们的所有调用都记录在 Mock.mock_calls 属性,您可以对它们的调用顺序进行断言。

    我简单地通过在 源锁定(_M) 对象,但也可以使用 Mock.attach_mock() method 将以不同方式创建的模拟附加到父级。

        2
  •  1
  •   hspandher    9 年前

    在我看来,测试或特别是TDD的真正目的是拥有更好的设计代码。如果为代码编写测试变得困难,那么这意味着您的代码高度耦合,您需要对其进行重构。此外,编写断言函数顺序的测试会使测试与代码过于耦合,并且非常脆弱。

    话虽如此,您可以用一种有点粗俗的方式测试订单。例如,您有两个名为 func_a func_b ,您希望确保 函数_a 之前调用过 函数_b 代替 函数_a 带有一个mock,该mock返回一些随机值,从而停止执行。嘲弄 函数_b 并确保 函数_a 被调用,并且 函数_b 未调用。对于其他排列,您也需要这样做。