之前的一篇博文提到过利用打算利用python写个mock系统以方便测试,主要是因为所测系统A依赖于其他系统的输入,两个系统属于不同的项目且开发和测试成员都不同,单独针对A系统进行测试时由于A的依赖性导致很多测试点无法覆盖且由于分属不同项目联调成本也较高,于是乎想到通过Mock的方式规避此问题,由于小弟之前只会java,所以第一时间想到的是用java编写一个mock系统,但是被测系统是C++实现的,那么就涉及到网络字节序的转换问题,研究了半天后开写,接收到的请求死活不能正确解析出来,而且发现代码还写了不少,头大,旁边同事在研究python,在他的强烈推荐下我就考虑怎么用python去实现,利用业余时间突击学习了一个月的python,终于大功告成,下面记录一下我的学习历程和收获!
1.迅速翻阅《python核心编程》第一部分,以及第二部分的“网络编程”章节(因为涉及两个系统的通信),由于有java的经验上手还是比较快的。
2.根据书中内容用python编写个简单的Socket服务端,能接收到被测系统的请求;这时谷歌上搜到python已经有SocketServer模块,只要引入它及它的子类StreamRequestHandler并重写handler方法(具体请求处理)。于是接下来考虑handler方法的具体实现,主要分两部分:1.请求的接收2.请求结果的返回;第一部分查看python官方文档轻松实现,第二部分先根据两个系统间的请求和反馈格式拼装内容,拼装完后考虑到python没有Byte类型,如何将拼装的内容转化为字节流并且让C++实现的系统能够识别呢?网上搜了搜,发现有struct这个好东西!利用它的pack方法可以将内容转换成指定的格式,pack方法有两个参数,一是转换后的格式定义,二是待转换的内容,下面贴上格式定义符与C++和python中的对应关系:
> 格式 |
c类型 |
python类型 |
> x |
char |
无(表示填充字节) |
> c |
char |
长度为1的字符串 |
> b |
signed char |
integer |
> B |
unsigned char |
integer |
> h |
short |
integer |
> H |
unsigned short |
integer |
> i |
int |
integer |
> I |
unsigned int |
long |
> l |
long |
integer |
> L |
unsigned long |
long |
> q |
long long |
long |
> Q |
unsigned long long |
long |
> f |
float |
float |
> d |
double |
float |
> s |
char[] |
string |
> p |
char[] |
string |
> P |
void* |
integer |
默认情况下struct根据本地机器字节顺序转换.不过可以用格式中的第一个字符来改变对齐方式.定义如下:
> 字符 |
字节顺序 |
长度和对齐方式 |
> @ |
native |
native |
> = |
native |
standard |
> < |
little-endian |
standard |
> > |
big-endian |
standard |
> ! |
network (= big-endian) |
standard |
例如两个系统事先定义的通信格式为:一个整型、两个长整型、一个长度为8的字符数组,那么转换格式符为:!i2l8s或者!illssssssss
有了上面这个对应表,格式转换的问题轻松搞定,实验成功可以接收请求和返回内容
3.虽然实现了但还是觉得不够完美,尤其是response内容的拼装,是一个个写死并一个个传入到pack方法中的,如果response内容很长那么就显得特别丑陋而且也不够灵活。网上找了半天,发现不用一个个传递进去,可以先将内容写入列表或元组中,再在pack方法中用*列表或*元组可实现将这些参数依次传递到pack方法中
4.经过上一步骤,代码美观不少,但灵活性依旧没有解决,于是想到将这些参数变成配置文件,程序中解析配置文件内容再将内容写入列表中再传递到方法中,于是网上找了找python怎么解析xml,方法很多,最终选择了使用minidom解析,没有理由,也不知道它的优缺点,只是找到了一个具体的示例并且看懂了于是乎就决定用它了,这个东东的特性以及其他解析方式后续再研究,使用它解析时还是费了一番周折,其实原理就是把xml文件中的每一个节点当做叶子节点,可以层层解析也可以解析指定的节点,而且节点内容是该节点的子节点(叶子节点)。
<?xml version="1.0" encoding="UTF-8"?>
<response>
<head>
<version>420</version>
<command>420</command>
<passwd>12345678</passwd>
<type>1</type>
<status>0</status>
<src>4</src>
<dest>1</dest>
<serializationHigh>1234567</serializationHigh>
<serializationLow>7654321</serializationLow>
<body_length>60</body_length>
<result_length>2</result_length>
</head>
<result>
<iids>2000000001</iids>
<gids>10000617005</gids>
<similaritys>95</similaritys>
<image_type>0</image_type>
<dimensions>5</dimensions>
</result>
<result>
<iids>2000000006</iids>
<gids>10000617006</gids>
<similaritys>95</similaritys>
<image_type>0</image_type>
<dimensions>5</dimensions>
</result>
</response>
#!/usr/bin/python
# encoding: utf-8
'''
com.test.mockvsearch -- shortdesc
com.test.mockvsearch is a description
It defines classes_and_methods
@author: user_name
@copyright: 2013 organization_name. All rights reserved.
@license: license
@contact: user_email
@deffield updated: Updated
'''
import sys
import struct
import string
import types
from xml.dom import minidom
from SocketServer import (TCPServer as SERV,StreamRequestHandler as SRH)
# 定义获取协议头内容的方法
def gethead(a,b):
nodes=a.getElementsByTagName(b).item(0);
head=[];
for value in nodes.childNodes:
if value.nodeName=='version':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='command':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='passwd':
head.append(str(value.firstChild.nodeValue))
elif value.nodeName=='type':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='status':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='command':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='src':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='dest':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='serializationHigh':
head.append(string.atol(value.firstChild.nodeValue))
elif value.nodeName=='serializationLow':
head.append(string.atol(value.firstChild.nodeValue))
elif value.nodeName=='body_length':
head.append(string.atoi(value.firstChild.nodeValue))
elif value.nodeName=='result_length':
head.append(string.atoi(value.firstChild.nodeValue))
return head;
#定义获取协议体内容的方法
def getbody(element,bodyname):
body=[];
nodes=element.getElementsByTagName(bodyname);
for i in range(nodes.length):
for node in nodes.item(i).childNodes:
if node.nodeName=='iids':
body.append(string.atol(node.firstChild.nodeValue));
if node.nodeName=='gids':
body.append(string.atol(node.firstChild.nodeValue));
if node.nodeName=='similaritys':
body.append(string.atoi(node.firstChild.nodeValue));
if node.nodeName=='image_type':
body.append(string.atoi(node.firstChild.nodeValue));
if node.nodeName=='dimensions':
body.append(string.atoi(node.firstChild.nodeValue));
return body;
#定义消息格式的方法
def getbodyformat(list):
format='';
for var in list:
if type(var) is types.IntType:
format+='i';
if type(var) is types.LongType:
format+='Q';
return format;
doc = minidom.parse(sys.argv[1]);
root= doc.documentElement;
#消息头格式
headformat="!2i8s4i2q2i"
#消息头内容
body1=gethead(root,'head');
#消息体内容
body2=getbody(root, 'result');
#消息体格式化
bodyformat=getbodyformat(body2);
#整个消息的格式化信息
rformat=headformat+bodyformat;
#整个响应消息的内容
response=body1+body2;
HOST='localhost'
PORT=8888;
ADDR=(HOST,PORT);
#定义请求响应处理类
class MyHandler(SRH):
def handle(self):
#接收请求
MyData = self.request.recv(2048000);
#打印请求长度
print 'result length is:', len(MyData);
#打印请求内容和转换格式
print response,rformat;
#拼装响应内容
senddata=struct.pack(rformat,*response);
#发送响应内容
self.request.send(senddata);
#创建Socket服务
myServer=SERV(ADDR,MyHandler);
#进入循环状态
myServer.serve_forever();
相关推荐
Python Django框架是一个强大的Web开发平台,而将Django应用于构建MockServer,则能够帮助开发者在API实际服务未就绪之前进行前端开发或集成测试。本文将深入探讨如何利用Python Django来创建一个MockServer,以支持...
首先,系统架构部分将解释如何利用Python的测试框架如unittest或pytest来搭建基础,以及如何集成Selenium、Appium等工具进行Web和移动应用的自动化测试。其次,功能模块可能包括测试用例管理、测试执行、结果分析和...
通过以上步骤,我们可以构建出一个功能完备的Django Mock系统,为开发团队提供可靠的API模拟环境,从而提高开发效率和软件质量。在实际项目中,还可以考虑添加日志记录、权限控制、性能监控等功能,以满足更高的需求...
Python是一种广泛应用于各种领域的编程语言,特别是在测试领域,它的易用性和丰富的库使其成为理想的工具。...通过深入学习和实践,你将能够充分利用Python在测试中的各种优势,实现更高效、更稳定的软件开发。
本文将详细探讨如何利用Python语言来设计一个自动化测试系统,结合提供的"Python语言下的自动化测试系统设计.pdf"文件,我们将深入解析其中的关键知识点。 一、Python在自动化测试中的优势 Python以其简洁的语法、...
`mock`提供了一个隔离的环境来构建RPM包,避免对主机系统产生影响。 **一、Mock工具简介** Mock是一个用于构建RPM包的工具,它可以在一个隔离的环境中运行,这个环境称为chroot。Mock会根据配置文件创建一个与目标...
**PyPI 官网下载 | robotframework-mockserver-0.0.4.tar.gz** `robotframework-mockserver-0.0.4.tar.gz` 是一...通过在PyPI上发布,开发者可以轻松地将其集成到他们的项目中,利用Python的生态系统进行自动化测试。
`django_mock_queries`是这个项目的名称,`0.0.16.4`是特定的版本标识,而`.tar.gz`是Unix/Linux系统常用的归档和压缩格式,通常用于在Python中分发源代码包。 标签中的"django python 后端 开发语言 Python库"为...
"Python-HackSoft项目"显然利用了Django的强大功能来构建内容管理系统(CMS)。遵循良好的编程风格和指南是任何项目成功的关键,特别是对于团队合作的项目。这份"HackSoft项目中使用的Django风格指南"应该提供了关于...
在云原生环境中,flake8-mock可以帮助开发者遵循最佳实践,编写更高质量的Python代码,特别是涉及Zookeeper或其他分布式系统组件的代码。 总之,flake8-mock是一个增强flake8功能的插件,专注于检查Python测试代码...
在这个实例中,脚本可能利用了Python的事件模拟库,如`unittest.mock`或自定义的模拟类,来生成和处理模拟事件。 在源代码中,你可能会看到以下几个关键知识点: 1. **事件模拟**:Monkey脚本的核心是模拟用户输入...
此外,书中还可能涉及到一些与Python编程环境相关的其他知识点,比如如何使用虚拟环境(Virtual Environments)来管理项目依赖,以及如何利用构建工具(如setuptools)来打包和分发Python包。 尽管上述内容是基于对...
1. **版本兼容性**: 确保提供的离线包与目标系统的Python版本和操作系统兼容。 2. **依赖管理**: 离线包应包含所有必要的依赖,避免因缺少依赖导致的安装失败。 3. **更新维护**: 定期更新离线包,以保持测试库和...
本书“Pro Python Best Practices Debugging, Testing and Maintenance”深入探讨了这些主题,旨在帮助开发者构建更稳定、更可维护的软件系统。以下是对这些核心概念的详细解读。 **调试**: 调试是找出并修复程序...
在这个主题中,我们将深入探讨Python在构建和测试Web接口方面的能力,以及如何利用其丰富的库和框架来实现高效的工作流程。 1. Python基础:Python是一种高级编程语言,以其简洁的语法和强大的功能而受到广大开发者...
Python的unittest.mock库可以帮助我们模拟外部依赖,使得集成测试更加可控。 3. 系统测试:系统测试是验证整个系统是否满足需求规格,包括功能、性能、安全性和兼容性等方面。在这个阶段,可能会使用到selenium这样...
Python Web接口开发与测试是现代软件工程中的重要环节,它涉及到使用Python语言构建Web服务以及对这些服务进行验证和质量保证。在这个过程中,开发者需要掌握一系列技术和工具,以确保接口功能完善、性能良好且易于...
在智能停车领域,Python语言因其简洁的语法和丰富的库支持,成为了自动化测试的重要工具。本文将深入探讨Python在...开发者应当充分利用Python的丰富资源,构建高效、全面的测试体系,以保障智能停车系统的高质量运行。
本文将深入探讨如何利用Python实现自动化,包括基础概念、关键库的使用以及实际应用案例。 首先,Python的基础是其语法结构。自动化通常涉及到文件操作、数据处理和系统交互。例如,`os`库可以用来创建、删除和管理...
Python是一种广泛应用于各种领域的编程语言,特别是在自动化测试中,它凭借其简洁的语法和丰富的库支持,...通过深入学习和实践,你将能够利用Python实现更加智能和可靠的测试解决方案,提高软件质量,降低维护成本。