我在测试驱动的开发中阅读了official tutorial,但在我的情况下它并没有很大帮助。我编写了一个小型库,大量使用twisted.web.client.Agent
及其子类(例如BrowserLikeRedirectAgent
),但我一直在努力使教程的代码适应我自己的测试用例。
我看了twisted.web.test.test_web
,但我不明白如何将所有部分组合在一起。例如,根据官方教程,我仍然不知道如何从Protocol
获取Agent
个对象
有人能告诉我如何编写一些简单的测试,用于依赖Agent到GET
和POST
数据的代码吗?我们非常欢迎任何其他细节或建议......
非常感谢!
答案 0 :(得分:3)
如何使用@inlineCallbacks
使生活更简单(即代码更具可读性)。
事实上,我甚至建议不要直接使用Deferred
,除非对性能或特定用例绝对必要,而是始终坚持@inlineCallbacks
- 这样你就可以使你的代码看起来像普通代码,同时受益于非阻塞行为:
from twisted.internet import reactor
from twisted.web.client import Agent
from twisted.internet.defer import inlineCallbacks
from twisted.trial import unittest
from twisted.web.http_headers import Headers
from twisted.internet.error import DNSLookupError
class SomeTestCase(unittest.TestCase):
@inlineCallbacks
def test_smth(self):
ag = Agent(reactor)
response = yield ag.request('GET', 'http://example.com/', Headers({'User-Agent': ['Twisted Web Client Example']}), None)
self.assertEquals(response.code, 200)
@inlineCallbacks
def test_exception(self):
ag = Agent(reactor)
try:
yield ag.request('GET', 'http://exampleeee.com/', Headers({'User-Agent': ['Twisted Web Client Example']}), None)
except DNSLookupError:
pass
else:
self.fail()
试用应该照顾其余部分(即等待测试函数返回的Deferred
(@inlineCallbacks
- 包裹的callables也“神奇地”返回Deferred
- 我强烈建议如果您还不熟悉,请在@inlineCallbacks
上阅读更多内容。
P.S。还有一个用于测试的Twisted“插件”,可以让你从测试函数中返回Deferred
并让他们等到它们被解雇,然后退出:http://nose.readthedocs.org/en/latest/api/twistedtools.html
答案 1 :(得分:2)
这类似于迈克所说的,但试图测试响应处理。还有其他方法可以做到这一点,但我喜欢这种方式。此外,我同意测试包装代理的东西并不太有用,并且在协议中测试协议/保持逻辑可能更好,但有时你只想添加一些绿色滴答。
class MockResponse(object):
def __init__(self, response_string):
self.response_string = response_string
def deliverBody(self, protocol):
protocol.dataReceived(self.response_string)
protocol.connectionLost(None)
class MockAgentDeliverStuff(Agent):
def request(self, method, uri, headers=None, bodyProducer=None):
d = Deferred()
reactor.callLater(0, d.callback, MockResponse(response_body))
return d
class MyWrapperTestCase(unittest.TestCase):
def setUp:(self):
agent = MockAgentDeliverStuff(reactor)
self.wrapper_object = MyWrapper(agent)
@inlineCallbacks
def test_something(self):
response_object = yield self.wrapper_object("example.com")
self.assertEqual(response_object, expected_object)
答案 2 :(得分:0)
这个怎么样?对以下内容进行试用。基本上你只是嘲笑代理并假装它像宣传的那样,并且使用FakeAgent(在这种情况下)使所有请求失败。如果你真的想把数据注入到传输中,那我认为这样做会“更多”。但是,你真的在测试你的代码吗?还是代理商?
from twisted.web import client
from twisted.internet import reactor, defer
class BidnessLogik(object):
def __init__(self, agent):
self.agent = agent
self.money = None
def make_moneee_quik(self):
d = self.agent.request('GET', 'http://no.traffic.plz')
d.addCallback(self.made_the_money).addErrback(self.no_dice)
return d
def made_the_money(self, *args):
##print "Moneeyyyy!"
self.money = True
return 'money'
def no_dice(self, fail):
##print "Better luck next time!!"
self.money = False
return 'no dice'
class FailingAgent(client.Agent):
expected_uri = 'http://no.traffic.plz'
expected_method = 'GET'
reasons = ['No Reason']
test = None
def request(self, method, uri, **kw):
if self.test:
self.test.assertEqual(self.expected_uri, uri)
self.test.assertEqual(self.expected_method, method)
self.test.assertEqual([], kw.keys())
return defer.fail(client.ResponseFailed(reasons=self.reasons,
response=None))
class TestRequest(unittest.TestCase):
def setUp(self):
self.agent = FailingAgent(reactor)
self.agent.test = self
@defer.inlineCallbacks
def test_foo(self):
bid = BidnessLogik(self.agent)
resp = yield bid.make_moneee_quik()
self.assertEqual(resp, 'no dice')
self.assertEqual(False, bid.money)