这几天兼职测试工程师,有一个WebService服务,虽然SoapUI提供了很好的WS服务测试功能,但是作为一个有理想有追求的程序员,怎么可以放弃任何一个写代码的机会呢,于是,一个用python写自动化测试脚本的我就诞生了。
SoapUI的官网 https://www.soapui.org/ 里面也有源码,有兴趣的可以研究一下WS调用的内部原理。
suds是一个基于SOAP的python客户端,可以实时地读取wsdl的内容,进而可以调用wsdl里定义的WebService服务,就可以满足我测试的需求啦(当然它不只是用来做测试的)
首先要安装suds,可以通过pip来安装这个模块
pip install suds
完成安装后就可以在python代码里通过import suds使用相关的功能。
常规的使用方法
url = ‘http://localhost:8080/webservice/simpleService?wsdl‘ client = suds.client.Client(url) service = client.service
简单类型的参数可以直接传递,比如string,boolean,int
比如下面调用doSomething服务方法
result = service.doSomething(‘I am a request!‘)
复杂对象类型需要通过client提供的工厂方式来生成
比如
#创建Request对象,该类型定义在wsdl中,如果有多个schema,则需要增加前缀,比如ns0、ns1等 request = client.factory.create(‘Request‘) #打印request对象,可以查看对象内部的字段 print request #设置request对象中info字段的值 request.info = ‘‘ #调用doSomething服务,参数为request对象,返回值为response对象 response = service.doSomething(request) #打印response对象,查看返回对象的内容 print response
上面的simpleService是自己写的例子,用来说明suds的简单使用。
那么问题来了,实际测试的WebService中定义了多个schema,每个schema拥有不同的并且定义的类型之间互相嵌套,比如:
ns0中定义了A类型的对象,ns1中定义了B类型的对象, 且A对象中有一个属性是B类型的
Class A {
private Class B;
}
通过client.factory.create(‘ns0:A’)构造A对象,报以下错误:
An error occured while building a instance of (ns3:A). As a result
the object you requested could not be constructed. It is recommended
that you construct the type manually using a Suds object.
Please open a ticket with a description of this error.
Reason: Type not found: ‘(B, http://****************, )‘
刚开始以为是B在wsdl里没有定义,后来用client.factory.create(‘ns1:B’)来创建B对象是成功的。
搜了很多资料都只是关于怎么使用suds的,没有提及这个问题,苦思冥想,后来突然看到wsdl里<wsld:types>标签下定义了很多个schema,怀疑是不是跨schema引用会找不到类型,所以报了TypeNotFound。于是去找了官方文档,https://fedorahosted.org/suds/
发现创建client对象的方法中有一个options参数,里面有一个bool类型的值autoblend
文档的说明是Flag that ensures that the schema(s) defined within the WSDL import each other.
意思是说这个参数是使得wsdl中定义的schema互相引入,所以可能之前的猜测是正确的
带着试一试的心态改了代码 client = suds.client.Client(url, autoblend = True)
Bingo!成功。
总结:归根接地是没有好好理解WebService的原理和机制,尤其是对WSDL内容的不熟悉,导致了没有第一时间意识到问题所在。有空好好研究一下WSDL的解析原理,以及为什么会有schema相互引入这么一回事儿。