检测方法是否递归而不调用它?

时间:2015-08-04 16:13:52

标签: python unit-testing recursion inspect

这可能听起来像是想要实现的愚蠢的事情。上下文是测试驱动的开发:我有一个方法,它涉及逐步通过树的节点,并开发这个功能,我已经走了:
"查看子节点"
"如果子节点有子节点,则查看孙子节点"
"如果孙子节点有子节点,则查看曾孙子节点" ...等。

因此,您必须使用递归方法替换此代码。如果您正在使用TDD,那么您希望编写一个断言语句,如果您的方法不是递归的,则该语句将失败。对于非TDD人来说这可能听起来很愚蠢,但有一点是树通常涉及相当多的递归功能,所以它实际上感觉不好"跳过这种测试步骤!

我想知道检查模块是否有我需要的东西......但是我很挣扎。在我看来,在一个理想的世界中,你会想要检测这种递归,而不必实际调用该方法。

2 个答案:

答案 0 :(得分:3)

您无法可靠地检查函数是否使用递归,否。

一个简单的递归函数会查找一个具有相同名称的全局函数并调用它,因此您必须查看函数字节码或将字节码解析为AST并尝试查找对全局对象的调用同名。但是如果正在使用方法或者函数是别名的,那么你将面临更难的检测。

此外,您通常会测试被测对象的功能,而不是具体实现。测试所需的结果,而不是如何生成这些结果。

也许你想避免递归,因为你可能会用完堆栈。在这种情况下,你将测试你是否会用完堆栈

将堆栈深度设置为较小的数字(使用sys.setrecursionlimit()),创建一个比堆栈更多级别的树,然后尝试解析它。如果抛出RuntimeError异常,则使用递归或其他依赖Python调用堆栈的方法太多。

答案 1 :(得分:0)

即使在进行'TDD'时,检查方法是否递归也不是一个好主意。想一想,即使你发现这个方法是递归的,也有一千个可以做的事情。这个递归代码错误

相反,在进行TDD时,想出一些小但很好的数据集表示,您将进行处理,并编写案例来检查天气,您正在编写的函数可以很好地处理它们。

让我们考虑一个递归函数的例子,用于解析和查找树节点的总和。

def total(tree):
    if tree == None: return 0
    return total(tree.left) + total(tree.right) + tree.cargo

以下是我考虑测试functionality而不是测试implementation函数的一些测试数据案例:

确保总计正确的正面测试

  1. 当我在树中有一个节点时,总校正
  2. 当我有一个节点和两个第一级孩子时,总数是否正确
  3. 当我只有一个三级别的右孩子(左孩子失踪)是完全正确的 。
  4. 然后测试一些退出条件:

    1. 使用示例树初始化测试,并根据您希望实施的算法检查您的函数是否在预期节点上退出 。
    2. 添加一些否定测试

      1. 如果树结构中存在循环,请检查抛出的异常 。
      2. 依此类推......直到你介绍了一些基本的组合。上升两个2级。

        现在您知道要通过这些测试,您的函数将不得不执行right事务,递归与否。 是单元测试的目的。测试功能,而不是实施的详细信息。

        一旦您确信您的测试是健壮的,并且任何通过这些测试的功能都是一个很好的功能,那么如何实现该功能是无关紧要的。它可能是也可能不是递归的,但是在编写单元测试时,你不关心