代码之家  ›  专栏  ›  技术社区  ›  sokeefe

测试递归Python函数

  •  3
  • sokeefe  · 技术社区  · 7 年前

    def factorial(n):
      if bool_function(n):
          return 1
      else:
          return n * factorial(n-1)
    

    测试或模拟布尔_函数(n)的最佳方法是什么,以便第一次迭代为真,之后的任何调用为假?

    5 回复  |  直到 7 年前
        1
  •  5
  •   juanpa.arrivillaga    7 年前

    您始终可以实现一个类来封装状态,并为您提供更大的灵活性,下面是一个示意图:

    >>> class MockBoolCheck:
    ...     def __init__(self, fail_after=0):
    ...         self.count = 0
    ...         self.fail_after = fail_after
    ...     def __call__(self, n):
    ...         called = self.count
    ...         self.count += 1
    ...         return called <= self.fail_after
    ...
    >>> bool_function = MockBoolCheck()
    >>> bool_function(42)
    True
    >>> bool_function(42)
    False
    >>> bool_function(42)
    False
    >>> bool_function(42)
    False
    >>> bool_function(42)
    False
    
        2
  •  1
  •   Sergey Vasilyev    7 年前

    # Your code (or module):
    
    def bool_function(n):
        print('REAL bool-function {}'.format(n))
        return n <= 0
    
    def factorial(n):
        print('FACT {}'.format(n))
        if bool_function(n):
            return 1
        else:
            return n * factorial(n-1)
    
    # Mocking code (or module):
    
    def mock_function(n):
        print('MOCK bool-function {}'.format(n))
        global bool_function
        bool_function = bool_func_orig  # restore on the first use
        return False
    bool_func_orig = bool_function
    bool_function = mock_function  # mock it
    
    # Go run it!
    factorial(10)
    

    如果这是两个独立的模块,则 global bool_function & bool_function=... somemodule.bool_function=... .

    如果您想使用mocking库,那么这取决于您使用的库。如果是这样的话 unittest.mock ,那么你应该玩 side_effect=... wraps=... (参见 manual ). 同样的方法:模仿它,并在第一次使用时从副作用内部取消模仿。

        3
  •  0
  •   Aaron    7 年前

    def factorial(n, debug=False):
      if bool_function(n) or debug:
          return 1
      else:
          return n * factorial(n-1)
    

    这自然意味着您也在进行外部测试 bool_function()

        4
  •  0
  •   taras    7 年前

    只需将函数作为参数传递。如果函数为None,您可以根据需要应用一些默认行为。

    这是在 queries to iterables (例如Django查询或Peewee查询)在大多数语言中。

    返回布尔值的函数通常称为 predicate

    def factorial(n, predicate=None):
      if not predicate:
         predicate = lambda x: x > 2
    
      if predicate(n):
          return 1
      else:
          return n * factorial(n-1)
    
        5
  •  0
  •   britodfbr    5 年前

    对于python>3.6

    import mock   
    class RecursividadeTest(unittest.TestCase):
        def test_recursive(self):
            with mock.patch('path.factorial') as mock_fact:
                factorial(3)
                self.assertTrue(mock_fact.called)
                self.assertGreaterEqual(mock_fact.call_count, 2)
    
        def test_recursive_2(self):
        with mock.patch('incolumepy.sequences.fibonacci.fibonacci') as mock_fib:
            for i in range(1, 5, -1):
                expected = i - 1
                fibonacci(i)
                self.assertTrue(mock_fib.called)
                self.assertEqual(mock_fib.call_count, expected)