之前在测试Django应用时,使用了非常方便的django.test.TestCase。在测试Tornado时,我也包装了一个TestCase类,提供和Django一样便捷的测试方法。最终,测试案例的代码将会是这样:
testclient.py的代码如下:
import tornado.ioloop import unittest import mimetypes
import tornado.httpclient import tornado.ioloop
TEST_PORT = 8989
def encode_multipart_formdata(fields, files): "““ fields is a sequence of (name, value) elements for regular form fields. files is a sequence of (name, filename, value) elements for data to be uploaded as files Return (content_type, body) ready for httplib.HTTP instance "““ BOUNDARY = '———-ThIs_Is_tHe_bouNdaRY_$' CRLF = '\r\n' L = [] for (key, value) in fields: L.append('–' + BOUNDARY) L.append('Content-Disposition: form-data; name=”%s"' % key) L.append('‘) L.append(value) for (key, filename, value) in files: L.append('–' + BOUNDARY) L.append('Content-Disposition: form-data; name=”%s”; filename=”%s"' % (key, filename)) L.append('Content-Type: %s' % get_content_type(filename)) L.append('‘) L.append(value) L.append('–' + BOUNDARY + '–') L.append('‘) body = CRLF.join(L) content_type = 'multipart/form-data; boundary=%s' % BOUNDARY return content_type, body
def get_content_type(filename): return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
class Response: def __init__(self, status_code, content): self.status_code = status_code self.content = content
class Client: def handle_request(self, response): self.response = response tornado.ioloop.IOLoop.instance().stop() def post(self, url, data={}): url = 'http://127.0.0.1:%s%s' % (TEST_PORT, url) fields = [] files = [] for key, value in data.items(): if isinstance(value, file): files.append([key, value.name, value.read()]) else: fields.append([key, value]) content_type, body = encode_multipart_formdata(fields, files) headers = {'Content-Type' : content_type} request = tornado.httpclient.HTTPRequest(url=url, method='POST', headers=headers, body=body)
client = tornado.httpclient.AsyncHTTPClient() client.fetch(request , self.handle_request) tornado.ioloop.IOLoop.instance().start() return Response(self.response.code, self.response.body) class TestCase(unittest.TestCase): def _pre_setup(self): pass def _post_teardown(self): pass def __call__(self, result=None): "““ Wrapper around default call method to perform My test set up. This means that user-defined Test Cases aren’t required to include a call to super().setUp(). "““ self.client = Client() try: self._pre_setup() except (KeyboardInterrupt, SystemExit): raise except Exception: import sys result.addError(self, sys.exc_info()) return super(TestCase, self).__call__(result) try: self._post_teardown() except (KeyboardInterrupt, SystemExit): raise except Exception: import sys result.addError(self, sys.exc_info()) return
[温馨提示]:该文章由原博客园导入而来,如排版效果不佳,请移步:http://www.cnblogs.com/coderzh/archive/2010/01/01/Tornado-Unit-Testing.html
作者:CoderZh
微信关注:hacker-thinking (代码随想)
本文出处:https://blog.coderzh.com/2010/01/01/Tornado-Unit-Testing/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。