在 Twisted 试用单元测试中使用 @inlineCallbacks
Using @inlineCallbacks in Twisted trial unit tests
我有一些试用单元测试。在我的代码库中,一些方法 return 延迟并添加了回调,而其他方法则用 @inlineCallbacks 修饰。我想 运行 没有反应堆的测试,因为有些方法不做任何 I/O。我认为 @inlineCallbacks 只是 return 一个延迟,所以调用回调(0)来触发它就足够了。好像不是这样的。这是一个最小的例子:
from twisted.trial import unittest
from twisted.internet.defer import inlineCallbacks, returnValue, Deferred
def addone(val):
d = Deferred()
def cbk(res):
return val + 1
d.addCallback(cbk)
return d
@inlineCallbacks
def call_addone(val):
res = yield addone(val)
returnValue(res)
class Tester(unittest.TestCase):
def test_addone(self):
d = addone(2)
d.callback(0) # whatever I pass is ignored
self.assertEqual(3, self.successResultOf(d))
def test_call_addone(self):
d = call_addone(4)
d.callback(0) # whatever I pass is set as deferred's result
self.assertEqual(5, self.successResultOf(d))
当我调用 addone(2) 时,我得到一个延迟,当我用回调 (0) 触发它时,它将 return 2+1。在这种情况下,传递给回调的值将被忽略。
在第二个测试中 call_addone(4) returns 也被推迟了。但在这种情况下,传递给它的参数将被忽略,return 值将是我传递给 callback() 的任何值。为什么?我显然遗漏了一些东西。
这是试用 运行ner 的输出:
test_trial
Tester
test_addone ... [OK]
test_call_addone ... [FAIL]
===============================================================================
[FAIL]
Traceback (most recent call last):
File "tests/test_trial.py", line 31, in test_call_addone
self.assertEqual(5, self.successResultOf(d))
File "/home/b/.local/share/virtualenvs/twproba-y019OThE/lib/python3.5/site-packages/twisted/trial/_synctest.py", line 432, in assertEqual
super(_Assertions, self).assertEqual(first, second, msg)
File "/usr/lib/python3.5/unittest/case.py", line 821, in assertEqual
assertion_func(first, second, msg=msg)
File "/usr/lib/python3.5/unittest/case.py", line 814, in _baseAssertEqual
raise self.failureException(msg)
twisted.trial.unittest.FailTest: 5 != 0
test_trial.Tester.test_call_addone
-------------------------------------------------------------------------------
Ran 2 tests in 0.029s
FAILED (failures=1, successes=1)
这些行非常错误(假定 call_addone
是用 inlineCallbacks
定义的):
d = call_addone(4)
d.callback(0) # whatever I pass is set as deferred's result
这伴随着这些行很奇怪(假设未使用 inlineCallbacks
):
d = addone(2)
d.callback(0) # whatever I pass is ignored
在这两种情况下,您都要求一些库代码创建 Deferred
,然后您的应用程序代码为 Deferred
提供结果。因为 addone
做你想做的事,显然 可以 以这种方式使用 Deferred
。但是,这不是一个好的做法。最佳做法是负责 creating 和 firing a Deferred
躺在同一个地方。因此,在这种情况下,随着 addone
.
的实施
你失败的测试失败的原因是你没有考虑 inlineCallbacks
的实现,它认为它确实负责触发 Deferred
它 returns。 Deferred
它 returns 是 而不是 addone
调用返回的 Deferred
。它保留 Deferred
给自己。
d
的结果在:
d = call_addone(4)
d.callback(0) # whatever I pass is set as deferred's result
是 0
正是因为您提供了 0 的结果。您已经将结果提供给 inlineCallbacks
-managed Deferred
并短路了所有其余的inlineCallbacks
的实施。如果 addone
返回的 Deferred
曾经触发过,您可能会看到 AlreadyCalledError
,因为 inlineCallbacks
会尝试向 d
提供结果,Deferred
你已经提供了一个结果给。
我有一些试用单元测试。在我的代码库中,一些方法 return 延迟并添加了回调,而其他方法则用 @inlineCallbacks 修饰。我想 运行 没有反应堆的测试,因为有些方法不做任何 I/O。我认为 @inlineCallbacks 只是 return 一个延迟,所以调用回调(0)来触发它就足够了。好像不是这样的。这是一个最小的例子:
from twisted.trial import unittest
from twisted.internet.defer import inlineCallbacks, returnValue, Deferred
def addone(val):
d = Deferred()
def cbk(res):
return val + 1
d.addCallback(cbk)
return d
@inlineCallbacks
def call_addone(val):
res = yield addone(val)
returnValue(res)
class Tester(unittest.TestCase):
def test_addone(self):
d = addone(2)
d.callback(0) # whatever I pass is ignored
self.assertEqual(3, self.successResultOf(d))
def test_call_addone(self):
d = call_addone(4)
d.callback(0) # whatever I pass is set as deferred's result
self.assertEqual(5, self.successResultOf(d))
当我调用 addone(2) 时,我得到一个延迟,当我用回调 (0) 触发它时,它将 return 2+1。在这种情况下,传递给回调的值将被忽略。 在第二个测试中 call_addone(4) returns 也被推迟了。但在这种情况下,传递给它的参数将被忽略,return 值将是我传递给 callback() 的任何值。为什么?我显然遗漏了一些东西。
这是试用 运行ner 的输出:
test_trial
Tester
test_addone ... [OK]
test_call_addone ... [FAIL]
===============================================================================
[FAIL]
Traceback (most recent call last):
File "tests/test_trial.py", line 31, in test_call_addone
self.assertEqual(5, self.successResultOf(d))
File "/home/b/.local/share/virtualenvs/twproba-y019OThE/lib/python3.5/site-packages/twisted/trial/_synctest.py", line 432, in assertEqual
super(_Assertions, self).assertEqual(first, second, msg)
File "/usr/lib/python3.5/unittest/case.py", line 821, in assertEqual
assertion_func(first, second, msg=msg)
File "/usr/lib/python3.5/unittest/case.py", line 814, in _baseAssertEqual
raise self.failureException(msg)
twisted.trial.unittest.FailTest: 5 != 0
test_trial.Tester.test_call_addone
-------------------------------------------------------------------------------
Ran 2 tests in 0.029s
FAILED (failures=1, successes=1)
这些行非常错误(假定 call_addone
是用 inlineCallbacks
定义的):
d = call_addone(4)
d.callback(0) # whatever I pass is set as deferred's result
这伴随着这些行很奇怪(假设未使用 inlineCallbacks
):
d = addone(2)
d.callback(0) # whatever I pass is ignored
在这两种情况下,您都要求一些库代码创建 Deferred
,然后您的应用程序代码为 Deferred
提供结果。因为 addone
做你想做的事,显然 可以 以这种方式使用 Deferred
。但是,这不是一个好的做法。最佳做法是负责 creating 和 firing a Deferred
躺在同一个地方。因此,在这种情况下,随着 addone
.
你失败的测试失败的原因是你没有考虑 inlineCallbacks
的实现,它认为它确实负责触发 Deferred
它 returns。 Deferred
它 returns 是 而不是 addone
调用返回的 Deferred
。它保留 Deferred
给自己。
d
的结果在:
d = call_addone(4)
d.callback(0) # whatever I pass is set as deferred's result
是 0
正是因为您提供了 0 的结果。您已经将结果提供给 inlineCallbacks
-managed Deferred
并短路了所有其余的inlineCallbacks
的实施。如果 addone
返回的 Deferred
曾经触发过,您可能会看到 AlreadyCalledError
,因为 inlineCallbacks
会尝试向 d
提供结果,Deferred
你已经提供了一个结果给。