帮助您度过龙卷风。
项目描述
Glinda 是tornado的配套库。这是一种尝试,让您在使用该框架时不那么痛苦。事实上,我想让它变得非常愉快。我开始在 Tornado 中开发 HTTP 端点并需要对其进行测试。tornado.testing包对于单独测试端点很方便。但是,当您有一个异步调用其他 HTTP 服务的 HTTP 服务时,您会怎么做。事实证明,测试并不像应有的那么容易。这是我要解决的第一件事,也是这个库要提供的第一件事——一种测试非平凡服务的方法。
一旦您可以测试您的应用程序,下一步就是编写一个很好地适合 WWW 的应用程序。Tornado 在处理细节的 HTTP 细节(例如,CTE、传输编码)方面做得非常好。它没有提供一种干净的方式来透明地处理表示,所以我决定也将它添加到这个库中。
内容处理
Tornado 有一些内部内容解码可以通过调用 tornado.web.RequestHandler 的 get_body_arguments方法来访问。它将专门解码基本表单数据,application/x-www-form-urlencoded和 multipart/form-data。其他任何事情都由您决定。 glinda公开了一个内容处理混合,它为标准 RequestHandler 注入了一个属性,该属性是解码的请求正文和编码响应的新方法。这是它的样子:
class MyHandler(glinda.content.HandlerMixin, web.RequestHandler):
def post(self, *args, **kwargs):
body_argument = self.request_body['arg']
# do stuff
self.send_response(response_dict)
self.finish()
if __name__ == '__main__':
glinda.content.register_text_type('application/json',
default_charset='utf-8',
dumper=json.dumps, loader=json.loads)
glinda.content.register_binary_type('application/msgpack',
msgpack.dumpb, msgpack.loadb)
当客户端发送一个内容类型为application/json的帖子时,它会根据 HTTP 标头将二进制正文解码为字符串,并在您引用request_body 属性时调用json.loads对正文进行解码。通过引发HTTPError(400)来处理失败,因此您不必担心处理格式错误的消息。send_response方法将负责根据任何包含的Accept标头 找出适当的内容类型。您所要做的就是为预期的内容类型安装编码和解码处理程序。
glinda.content包实现了RFC7231中描述的内容 处理。具体来说,它解码第 3.1 节中描述的请求主体 和第3.4.1和5.3节中描述的主动内容协商 。
测试
这是一个测试异步调用另一个服务的 Tornado 端点的示例。在这种情况下,应用程序与其他一些服务的 /add端点交互。如果不必运行服务的副本,单独进行测试可能会很棘手。您可以模拟出AsyncHTTPClient并返回虚假的期货,但这样做会产生令人讨厌的副作用,即隐藏内容类型或标头处理方式的缺陷——没有 HTTP 请求意味着您有未经测试的假设。
以下代码片段使用glinda.testing提供的ServiceLayer抽象来测试被测应用程序 。
from tornado import testing
from glinda.testing import services
class MyServiceTests(testing.AsyncHTTPTestCase):
def setUp(self):
service_layer = services.ServiceLayer()
self.service = service_layer['adder']
# TODO configured your application here using
# self.service.url_for('/add') or self.service.host
super(MyServiceTests, self).setUp()
def get_app(self):
return MyApplication()
def test_that_my_service_calls_other_service(self):
self.service.add_response(
services.Request('POST', '/add'),
services.Response(200, body='{"result": 10}'))
self.fetch(self.get_url('/do-stuff'), method='GET')
recorded = self.service.get_request('/add')
self.assertEqual(recorded.method, 'POST')
self.assertEqual(recorded.body, '[1,2,3,4]')
self.assertEqual(recorded.headers['Content-Type'], 'application/json')
通过实现标准的tornado.testing.AsyncHTTPTestCase.get_app方法来链接被测应用程序 。然后,您添加一个glinda.testing.services.ServiceLayer对象,并通过添加端点将其配置为看起来像您所依赖的服务,然后将您的应用程序配置为指向服务层。当您使用self.fetch(...)调用被测应用程序时,它将通过 Tornado 堆栈发送 HTTP 请求(使用测试ioloop) 到将适当响应的服务层。美妙之处在于整个 HTTP 堆栈都在本地运行,因此您可以轻松测试边缘案例,例如正确处理状态代码、自定义标头或格式错误的正文,而无需借助深度模拟。
在哪里?
资源 |
|
地位 |
|
下载 |
|
文档 |
|
问题 |
项目详情
下载文件
下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。