mock server —— 用于自动化测试

我们在测试某个模块的时候,该模块会依赖很多外部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)


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值