这个 DeprecationWarning ("callable is None") 有什么用?

cat*_*cat 4 python python-unittest

我正在编写一个模块,我正在使用unittest与实际代码一起编写单元测试。

有时(似乎几乎是不确定的),像下面这样的函数没有明确返回一个值,用self.assertRaises(mymodule.MyEmptyException, myfunc())(whereself指的是 的子类unittest.TestCase)断言会引发一个神秘的DeprecationWarning.

这是此类函数的示例:

def insertn(self, items, lidex):
    """( z y x -- z b y x )
    add a list of items to the stack at the given index"""
    iter(items)
    for idx, obj in enumerate(items):
        self.insert(lidex, obj)
        lidex += 1
Run Code Online (Sandbox Code Playgroud)

其对应的单元测试:

def test_insertn_fail(self):
    """expect failure during multiple insertion"""
    self.assertRaises(mouse16.BadInternalCallException,
        stack.insertn([8, 4, 12], 16))
    with self.assertRaises(TypeError):
        stack.insertn(8, 16)
Run Code Online (Sandbox Code Playgroud)

给出(例如):

./mousetesting.py:103: DeprecationWarning: callable is None
Run Code Online (Sandbox Code Playgroud)

我认为使函数具有非None返回值可能会解决问题(即return 0),但后来我得到(例如):

======================================================================
ERROR: test_insertn_fail (__main__.CoreStack)
expect failure during multiple insertion
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./mousetesting.py", line 103, in test_insertn_fail
    stack.insertn([8, 4, 12], 16))
  File "/usr/lib/python3.5/unittest/case.py", line 727, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "/usr/lib/python3.5/unittest/case.py", line 176, in handle
    callable_obj(*args, **kwargs)
TypeError: 'int' object is not callable

----------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

所以unittest模块试图调用一个函数的返回值......但没有抱怨None 也不callable

我对 Python 的内部结构知之甚少,无法理解这里发生了什么。我想避免我的测试以一种我不知道将来如何修复的方式中断,因为DeprecationWarning我忽略了。

我的函数(但只有其中一些,而不是所有时间?)是否必须返回(浪费内存的)闭包或无意义的 lambda 表达式来避免这种情况?或者我应该制作一个东西来检测测试是否正在进行,然后才返回一个无操作的 lambda?这似乎是为了避免DeprecationWarning.

Mar*_*ers 8

您使用self.assertRaises()不当。它必须为您调用测试函数,以捕获异常:

self.assertRaises(mouse16.BadInternalCallException,
    stack.insertn, [8, 4, 12], 16)
Run Code Online (Sandbox Code Playgroud)

你被传入结果中的stack.insertn()调用(没有引发异常,但返回要么None或整数来代替),而返回值是不可调用的。该方法的旧版本也接受None该参数,不再受支持,因此None传入时会出现弃用警告而不是整数。

更好的方法是self.assertRaises()用作上下文管理器:

with self.assertRaises(mouse16.BadInternalCallException):
    stack.insertn([8, 4, 12], 16)
Run Code Online (Sandbox Code Playgroud)