您的位置:首页 > 其它

mock server —— 用于自动化测试

2012-11-01 01:20 281 查看
我们在测试某个模块的时候,该模块会依赖很多外部http server,真实搭建这样的server有两个缺点:1、部署维护成本较大,太重不适合自动化测试,2、网络异常、超时、返回部分结果等特殊情况很难测试到,这时候如果用到mock就很方便了,这里来介绍一个简单的mock server。

功能描述

模拟http服务, 同时支持get及post访问方式

提供两种set方法供用户自定义http服务response_code及response_content

接口说明

set_code_handler_func(self, func) #设置code处理方法,func接受参数为path,返回状态码,如:path:/index.jsp?galaxy=test return:200

set_content_handler_func(self, func) #设置content处理方法,func接受参数为path,返回page content,如:path:/index.html return:"hello world!"

start(self) # 启动服务

stop(self) # 停止服务

测试样例

from galaxy.mock_server import http

## init
server = http.MockHTTPServer(port=8000) # 默认使用8000端口

## set handler func
'''
模拟http服务response_code及response_content,对应提供如下两种set方法,eg:
func_code = lambda path: 504
func_content = lambda path: "hello world = " + path

以上func接受参数为path,当以post方式请求时path=path + “?” + data
'''
server.set_code_handler_func(func_code)
server.set_content_handler_func(func_content)

## start server
server.start()

## request code eg:
url = "http://10.250.11.57:8000/"
query = "url=http://www.taobao.com"
try:
req = urllib2.Request(url + urllib.quote(query))
response = urllib2.urlopen(req)
print response.read()
response.close()
except Exception, err:
print str(err)

## stop server
server.stop()


mock_server_http.py

"""
Mock HTTP Server.

This module builds on BaseHTTPServer by implementing the standard GET and POST
requests in a fairly straightforward manner.
"""

__version__ = "1.0"

__all__ = ["MockHTTPRequestHandler", "MockHTTPServer"]

import os
import cgi
import time
import BaseHTTPServer
import SocketServer
import urllib
import shutil
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

import sys
sys.path.append("/usr/local/atest/atest-1.1.5/lib/")
import atest.log as log

class MockHTTPRequestHandler(SocketServer.ThreadingMixIn, BaseHTTPServer.BaseHTTPRequestHandler):

server_version = "MockHTTP/" + __version__

code_handler_func = None
content_handler_func = None
read_timeout = 0

def log_message(self, format, *args):

"""override for ignore any log."""

pass

def do_GET(self):

path = urllib.unquote(self.path)

log.debug("path: %s" % path)

self.__response(path)

def do_POST(self):

# Parse the form data posted

form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD':'POST',
'CONTENT_TYPE':self.headers['Content-Type'],
})

data = [field + "=" + form[field].value for field in form.keys()]
path = "%s?%s" % (self.path, "&".join(data))

log.debug("path: %s" % path)

self.__response(path)

def __response(self, path):

response_code = self.code_handler_func.im_func(path) if self.code_handler_func else 200
response_content = self.content_handler_func.im_func(path) if self.content_handler_func else ""

log.debug("code: %s, content: %s" % (response_code, response_content))

f = StringIO()
f.write(response_content)
length = f.tell()
f.seek(0)
self.send_response(response_code)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
if f:
sleep_time = float(self.read_timeout)/1000
log.debug("Sleep %s seconds" % sleep_time)
time.sleep(sleep_time)
shutil.copyfileobj(f, self.wfile)
f.close()

class MockHTTPServer:

def __init__(self, port=8000):

self._port = port
self._code_handler_func = None
self._content_handler_func = None
self._read_timeout = 0

self._pid = 0

def set_code_handler_func(self, func):

"""Code handler func, eg:
>>>def func(path): # /index.jsp?galaxy=test
...    return 200
@param func: lambda x: 200
"""

self._code_handler_func = func

def set_content_handler_func(self, func):

"""The same as set_code_handler_func"""

self._content_handler_func = func

def set_read_timeout(self, milliseconds):

"""Set read timeout"""

self._read_timeout = milliseconds

def _server(self, protocol="HTTP/1.0",
HandlerClass = MockHTTPRequestHandler,
ServerClass = BaseHTTPServer.HTTPServer):

server_address = ('', self._port)

HandlerClass.protocol_version = protocol
HandlerClass.code_handler_func = self._code_handler_func
HandlerClass.content_handler_func = self._content_handler_func
HandlerClass.read_timeout = self._read_timeout
HandlerClass.daemon_threads = True

httpd = ServerClass(server_address, HandlerClass)

sa = httpd.socket.getsockname()
log.info("Serving HTTP on %s port %s ..." % sa)

httpd.serve_forever()

def start(self):

log.info("Start mock http server ...")

child = os.fork()
if not child:
self._server()

self._pid = child

def stop(self):

log.info("Stop mock http server ...")

if self._pid:
os.kill(self._pid, 9)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: