开发者社区> 科技小毛> 正文

Tornado Unit Testing - Tornado应用的单元测试

简介:
+关注继续查看

之前在测试Django应用时,使用了非常方便的django.test.TestCase。在测试Tornado时,我也包装了一个TestCase类,提供和Django一样便捷的测试方法。最终,测试案例的代码将会是这样:

复制代码
from testclient import TestCase

class QueryTest(TestCase):
    
def setUp(self):
        
pass
    
def test_query(self):
        file 
= open('uploadfile.dat''rb')
        response 
= self.client.post('/query', { 'a''1''b''2', 'upload': file })

        self.failUnlessEqual(response.status_code, 
200)
        self.failUnlessEqual(response.content, 
'ok')
复制代码


testclient.py的代码如下: 

复制代码
ExpandedBlockStart.gif代码
#!/usr/bin/env python
#
coding:utf-8
#
#
 Copyright 2009 CoderZh.com.
#
 Licensed under the Apache License, Version 2.0 (the "License");
#
 you may not use this file except in compliance with the License.
#
 You may obtain a copy of the License at
#
#
     http://www.apache.org/licenses/LICENSE-2.0
#
#
 Unless required by applicable law or agreed to in writing, software
#
 distributed under the License is distributed on an "AS IS" BASIS,
#
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
 See the License for the specific language governing permissions and
#
 limitations under the License.

__author__ = 'CoderZh'


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
复制代码
 
本文转自CoderZh博客园博客,原文链接:http://www.cnblogs.com/coderzh/archive/2010/01/01/Tornado-Unit-Testing.html,如需转载请自行联系原作者
 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Python web服务器3: 静态服务器&并发web服务器
Python web服务器3: 静态服务器&并发web服务器
8 0
Python web服务器4: 网络通信
Python web服务器4: 网络通信
4 0
Google Java编程风格规范(2020年4月原版翻译)
Google Java Style Guide 这份文档是Google Java编程风格规范的完整定义。当且仅当一个Java源文件符合此文档中的规则, 我们才认为它符合Google的Java编程风格。 与其它的编程风格指南一样,这里所讨论的不仅仅是编码格式美不美观的问题, 同时也讨论一些约定及编码标准。然而,这份文档主要侧重于我们所普遍遵循的规则,
8 0
Python web服务器5: tcp-ip简介
Python web服务器5: tcp-ip简介
4 0
Android 开发规范(转载 Blankj 作品)
摘要 • 1 前言 • 2 AS 规范 • 3 命名规范 • 4 代码样式规范 • 5 资源文件规范 • 6 版本统一规范 • 7 第三方库规范 • 8 注释规范 • 9 测试规范 • 10 其他的一些规范 1 前言
7 0
增强版 Git Flow 模型
使用 Git 的最佳方式一直存在争议。那是因为 Git 本身只详细说明了基本的分支操作,这使得它的使用模式: 即分支模型——常常成为用户有意见的地方。虽然Git 分支模型能够帮助开发者减少其在更改代码库时带来的冲突。 Git Flow,是一种经常推荐给 Git 用户的分支模型。 也许一开始你对 Git Flow 的逻辑很感兴趣,但是直到你在实践中遇到了一些障碍。 毕竟,有无数的变量在起作用,没有一个单一的分支模型能在所有情况下都能很好地工作。
10 0
Vue3 的 Reactive 响应式到底是什么
​Vue 3 除了令人钦佩的性能改进,还带来了一些新功能。可以说,最重要的介绍是 `Composition API` 。在本文的第一部分中,我们将概括 Vue3 创建新 API 的动机:即,更好的组织和重用代码。在第二部分中,我们将重点讨论使用新API时较少讨论的方面,例如响应式特性。我将响应式特性其称为按需响应。
8 0
GitHub 上的超级 Python 游戏项目,不容错过!
今天分享一个超级牛的 GitHub 项目,是一个专门的基于 Pygame 开发小游戏的项目。该项目就开源在 G 站上,目前已经获得了 2.6K 的 Star 和 1.5K 的 Fork,可以说是超级牛掰了!
5 0
+关注
580
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载