在Twisted试验单元测试中使用@inlineCallbacks

时间:2018-01-05 11:26:24

标签: python twisted deferred trial

我有一些试验单元测试。在我的代码库中,一些方法返回延迟并添加了回调,而其他方法则使用@inlineCallbacks进行修饰。我想在没有反应器的情况下运行测试,因为有些方法不进行任何I / O.我认为@inlineCallbacks只返回一个延迟,所以调用回调(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)触发它时将返回2 + 1。在这种情况下,将忽略传递给回调的值。 在第二个测试中,call_addone(4)也返回延迟。但在这种情况下,传递给它的参数将被忽略,而返回值将是我传递给callback()的任何内容。为什么?我显然遗漏了一些东西。

以下是试用跑者的输出:

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)

1 个答案:

答案 0 :(得分: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。但是,这不是一个好习惯。最佳做法是将创建解雇 Deferred的责任放在同一个地方。因此,在这种情况下,执行addone

你的测试失败的原因是你没有考虑inlineCallbacks的实现,因为Deferred认为它确实负责解雇它返回的Deferred。它返回的Deferred addone调用返回的Deferred。它使d保持自身。

d = call_addone(4) d.callback(0) # whatever I pass is set as deferred's result 的结果:

0

inlineCallbacks正是因为您提供了0的结果。您已将结果提供给Deferred - 托管inlineCallbacks并将所有剩余的结果短路Deferred的实施。如果addone返回的AlreadyCalledError确实触发,您可能会看到inlineCallbacks,因为d会尝试将结果提供给Deferredusing UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { void Start() { HingeJoint hinge = GetComponent<HingeJoint>(); JointMotor motor = hinge.motor; motor.force = 100; motor.targetVelocity = 90; motor.freeSpin = false; hinge.motor = motor; hinge.useMotor = true; } } 1}}你已经提供了一个结果。