我几年没有做任何扭曲,并且已经开始使用较新的Agent风格的客户端http调用。使用Agent一直没问题,但测试让我很困惑(毕竟它已经扭曲了)。
我已经浏览了https://twistedmatrix.com/documents/current/core/howto/trial.html文档以及有关试用工具和代理本身的API。还有很多搜索。
我已经伪造了Agent,因为我不需要测试它。但是由于处理代理请求的处理和响应的步骤,我的测试代码变得讨厌,实现代理,协议等的嵌套层。我应该在哪里绘制这条线并且有一些工具我是避风港找不到?
这是一个最小的例子(SUT的幼稚实现):
from twisted.web.client import Agent, readBody
from twisted.internet import reactor
import json
class SystemUnderTest(object):
def __init__(self, url):
self.url = url
def action(self):
d = self._makeAgent().request("GET", self.url)
d.addCallback(self._cbSuccess)
return d
def _makeAgent(self):
''' It's own method so can be overridden in tests '''
return Agent(reactor)
def _cbSuccess(self, response):
d = readBody(response)
d.addCallback(self._cbParse)
return d
def _cbParse(self, data):
self.result = json.loads(data)
print self.result
使用测试模块:
from twisted.trial import unittest
from sut import SystemUnderTest
from twisted.internet import defer
from twisted.test import proto_helpers
class Test(unittest.TestCase):
def test1(self):
s_u_t = ExtendedSystemUnderTest(None)
d = s_u_t.action()
d.addCallback(self._checks, s_u_t)
return d
def _checks(self, result, s_u_t):
print result
self.assertEqual({'one':1}, s_u_t.result)
class ExtendedSystemUnderTest(SystemUnderTest):
def _makeAgent(self):
return FakeSuccessfulAgent("{'one':1}")
## Getting ridiculous below here...
class FakeReason(object):
def check(self, _):
return False
def __str__(self):
return "It's my reason"
class FakeResponse(object):
''' Implementation of IResponse '''
def __init__(self, content):
self.content = content
self.prot = proto_helpers.StringTransport()
self.code = 200
self.phrase = ''
def deliverBody(self, prot):
prot.makeConnection(self.prot)
prot.dataReceived(self.content)
# reason = FakeReason()
# prot.connectionLost(reason)
class FakeSuccessfulAgent(object):
''' Implementation of IAgent '''
def __init__(self, response):
self.response = response
def request(self, method, url):
return defer.succeed(FakeResponse(self.response))
答案 0 :(得分:2)
但测试令我感到困惑(毕竟它是扭曲的)。
热闹。
class ExtendedSystemUnderTest(SystemUnderTest):
def _makeAgent(self):
return FakeSuccessfulAgent("{'one':1}")
我建议你让代理使用普通参数。这比_makeAgent
之类的私有方法更方便。组成很棒。继承就是meh。
class FakeReason(object):
...
没有理由假装这个。只需使用twisted.python.failure.Failure
即可。您不会 伪造测试中的每个对象。如果你不假装它们就会妨碍你。
class FakeResponse(object):
...
这可能是好的和必要的。
class FakeSuccessfulAgent(object):
...
这也很可能是必要的。你应该让它实际上更像是IAgent
实现 - 声明它实现了接口,使用zope.interface.verify.verify{Class,Object}
来确保你得到实现写入等(例如request
有错误现在签名)。
实际上是将所有这些测试工具添加到Twisted自身的票证 - https://twistedmatrix.com/trac/ticket/4024。所以我不认为你真的很困惑,你基本上和项目本身在同一条轨道上。您只是因为Twisted尚未为您完成所有这些工作而感到痛苦。
另外,请注意,而不是:
class Test(unittest.TestCase):
def test1(self):
s_u_t = ExtendedSystemUnderTest(None)
d = s_u_t.action()
d.addCallback(self._checks, s_u_t)
return d
你可以写这样的东西(最好是这样):
class Test(unittest.TestCase):
def test1(self):
s_u_t = ExtendedSystemUnderTest(None)
d = s_u_t.action()
self._checks(s_u_t, self.successResultOf(d))
这是因为IAgent
的假实现是同步的。你知道它是同步的。到request
返回时,它返回的Deferred
已经有了结果。以这种方式编写测试意味着您可以稍微简化代码(即,您可以在某种程度上忽略它的异步性 - 因为它不是)并且它避免运行全局反应器是在试验中从测试方法返回Deferred
的原因。