首页 > 编程语言 >Python在接口测试中的应用

Python在接口测试中的应用

时间:2022-10-30 18:04:10浏览次数:46  
标签:__ Python text self 接口 测试 time type def


1. 介绍

接口测试的方式有很多,可以使用的工具有jmeter,postman,soapUI等,也可以自己写代码进行接口测试(Python,java,go等等),工具的使用相对来说都比较简单,开箱即用。但如果接口中定义了一些需要加解密、数字签名等一些动态计算时,工具就很无助,唯有写代码进行实现测试。所以要根据接口协议,有针对性的进行选择工具,当工具不适合项目时需要进行工具开发。对于工具开发选择语言,语言本身没有优劣之分,选择自己擅长的和合适的。相对于java,go语言,Python不需要编译,而且支持的库很多,是其特点;其支持http协议接口的有urllib,urllib2以及requests库,支持websocket协议的库有websockets、websocket-client,支持grpc的库有grpcio、grpcio-tools,以及支持图形界面的PyQt5。本文中使用的Python版本为3.9.0,下面简单介绍下http、websocket、grpc接口示例,最后介绍使用PyQt5打造自己的测试工具。

2. http协议接口

对于http协议接口,requests库用起来最方便,因此采用requests库来做http协议的接口测试。安装requests:

pip install requests

2.1 GET请求示例

天气查询接口:​​wthrcdn.etouch.cn/weather_min…​​

import requests
r = requests.get('http://wthrcdn.etouch.cn/weather_mini')
print(r.text)

输出结果:'{"status":1002,"desc":"invilad-citykey"}'

2.2 带参数的GET请求示例

参数:city 城市名称

import requests
data ={}
data['city']='北京'
r = requests.get('http://wthrcdn.etouch.cn/weather_mini',params=data)
print(r.text)

输出结果:

'{"data":{"yesterday":{"date":"31日星期二","high":"高温 27℃","fx":"南风","low":"低温 17℃","fl":"","type":"小雨"},"city":"北京","forecast":[{"date":"1日星期三","high":"高温 29℃","fengli":"","low":"低温 18℃","fengxiang":"南风","type":"晴"},{"date":"2日星期四","high":"高温 30℃","fengli":"","low":"低温 20℃","fengxiang":"南风","type":"晴"},{"date":"3日星期五","high":"高温 30℃","fengli":"","low":"低温 22℃","fengxiang":"南风","type":"阴"},{"date":"4日星期六","high":"高温 26℃","fengli":"","low":"低温 21℃","fengxiang":"南风","type":"中雨"},{"date":"5日星期天","high":"高温 26℃","fengli":"","low":"低温 20℃","fengxiang":" 东风","type":"小雨"}],"ganmao":"感冒易发期,外出请适当调整衣物,注意补充水分。","wendu":"23"},"status":1000,"desc":"OK"}'

假如服务对请求中city的一致性进行校验,header中需要传入Authorization,为city值的md5

import hashlib
data ={}
data['city']='合肥'
auth=hashlib.md5(data['city'].encode(encoding='utf-8')).hexdigest()
headers = {'Authorization': auth}
r = requests.get('http://wthrcdn.etouch.cn/weather_mini',params=data,headers=headers)
print(r.text)

输出结果:

'{"data":{"yesterday":{"date":"31日星期二","high":"高温 35℃","fx":"南风","low":"低温 25℃","fl":"","type":"晴"},"city":"合肥","forecast":[{"date":"1日星期三","high":"高温 30℃","fengli":"","low":"低温 24℃","fengxiang":"北风","type":"小雨"},{"date":"2日星期四","high":"高温 26℃","fengli":"","low":"低温 23℃","fengxiang":"西北风","type":"阴"},{"date":"3日星期五","high":"高温 29℃","fengli":"","low":"低温 23℃","fengxiang":"东风","type":"多云"},{"date":"4日星期六","high":"高温 29℃","fengli":"","low":"低温 24℃","fengxiang":"东风","type":"小雨"},{"date":"5日星期天","high":"高温 31℃","fengli":"","low":"低温 24℃","fengxiang":"东北风","type":"小雨"}],"ganmao":"感冒低发期,天气舒适,请注意多吃蔬菜水果,多喝水哦。","wendu":"26"},"status":1000,"desc":"OK"}'

2.3 POST请求示例

本示例使用requests官网示例,POST请求不再多介绍,可参考官网。Github API v3 接受编码为JSON的POST数据

import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))

3. Websocket协议接口

安装websockets库

pip install websockets

下面是一个NLP接口的例子,客户端连接服务端,发送文本,接收返回结果,其中文本需要进行base64加密。

import uuid
import websockets

async def send_msg(websocket):
text = '我要查余额'
bs = str(base64.b64encode(text.encode('utf-8')), 'utf-8')
sid = uuid.uuid4()
timestamp = str(int(time.time()) * 1000)
msg = '{"app":"test","sn":"123","timeStamp":"' + timestamp + '","version":"1.0.0","data":"' + bs + '",' \
'"sid":"' + str(sid) + '"} '
print(msg)
await websocket.send(msg)
rev_text = await websocket.recv()
print(rev_text)

async def client():
async with websockets.connect('ws://xxx.xxx.com/nlp') as websocket:
await send_msg(websocket)

if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(client())

执行结果示例:{"appid":"test","sn":"123","timeStamp":"1630586234000","version":"1.0.0","data":"5oiR6KaB5p+l6K+i5L2Z6aKd",sid":"4c6f5a64-2374-4616-9385-376c0d25bc1e"}{"code":"0000","msg":"succ","nlp":"{"sceneKey":"","sid":"d28c7631-54d9-493e-8db8-f67a5ecc2a25","uid":"d28c7631-54d9-493e-8db8-f67a5ecc2a25","text":"我要查询余额",,"semantic":[{"intent":"querybalance","intentName":"查询余额","intentCnxt":"","template":"{Query}余额","score":0.865519,"slots":[]}],"dialog":{"status":0,"uid":"","reaction":{"text":""},"slots":null},"answer":{"answerType":"","text":"","emotion":"","topic":"","topicID":"","type":"","question":{"question":"","question_ws":""}}}","extendData":"","sid":"d28c7631-54d9-493e-8db8-f67a5ecc2a25","last":true}

4. grpc协议接口

grpc协议需要Python 3.5版本以上,安装所需的库:

pip install grpcio
pip install grpcio-tools

下面以虚拟主播服务接口为例,服务使用了grpc双向流进行交互,与服务端建立连接后,会返回一个rtmp地址,推送虚拟主播视频流,向服务端发送文本,会驱动虚拟主播播报文本。

4.1 编写avatar.proto文件

syntax = "proto3";

package protocol;

message AvatarRequest {
string app = 1;
string timestamp = 2;
string version = 3;
string anchorId = 4;
string vcn = 5;
bytes data = 6;
int32 width = 7;
int32 height = 8;
string type=9;

}

message AvatarResponse {
string code = 1;
string msg = 2;
string type = 3;
bytes data = 4;
string status = 5;
string sessionId = 6;
}

service AvatarInteraction {
rpc Interact (stream AvatarRequest) returns (stream AvatarResponse) {
}
}

4.2 使用工具生成grpc代码

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./avatar.proto最终生成avatar_pb2.py和avatar_pb2_grpc.py两个文件

4.3 grpc请求示例

将上述两个文件,引入到项目代码中

import sys
import threading
import time
import grpc
import avatar_pb2 as pb
import avatar_pb2_grpc as avatar


class avatarClient(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.status = False
self.serverUrl = ""
self.anchorId = '1001'
self.vcn = 'xiaoyuan'
self.app = 'testapp'
self.type = '0'
self.sendTxt = False
self.text = ""
self.connectType = '1001'
self.pingType = '-1000'
self.width = 1080
self.height = 1920
self.sid = ""
self.print_res = printRes()
self.lastPingTime = int(time.time() * 1000)

# 连接服务
def connect_sever(self):
return pb.AvatarRequest(app=self.app, timestamp=str(int(time.time() * 1000)), version='1.0.0',
anchorId=self.anchorId, vcn=self.vcn, type=self.connectType, width=self.width,
height=self.height)

# 发送文本
def send_text(self):
return pb.AvatarRequest(app=self.app, timestamp=str(int(time.time() * 1000)), version='1.0.0',
anchorId=self.anchorId, vcn=self.vcn, type='3', data=str(self.text).encode('utf-8'))

# 发送ping
def send_ping(self):
return pb.AvatarRequest(app=self.app, timestamp=str(int(time.time() * 1000)), version='1.0.0',
anchorId=self.anchorId, vcn=self.vcn, type=self.pingType)

def send_message(self):
yield self.connect_sever()
#间隔10秒,发送ping,进行连接保活
while True:
if self.sendTxt:
yield self.send_text()
self.sendTxt = False
if (int(time.time() * 1000) - int(self.lastPingTime)) < 10000:
continue
else:
yield self.send_ping()
self.lastPingTime = int(time.time() * 1000)

def run(self):
self.status = True
if self.serverUrl == "":
return
with grpc.insecure_channel(self.serverUrl) as channel:
stub = avatar.AvatarInteractionStub(channel)
self.channel = channel
responses = stub.Interact(self.send_message())

self.print_res.setClient(responses, self)
self.print_res.start()
time.sleep(1)
while True:
if self.print_res.runStatus == False:
break
client.text = input("input your text:\n")
client.sendTxt = True
time.sleep(1)

def stop(self):
try:
self.status = False
self.print_res.runStatus = False
time.sleep(1)
except KeyboardInterrupt:
pass


class printRes(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.runStatus = True

def setClient(self, responses, client):
self.responses = responses
self.client = client

def run(self):
try:
for response in self.responses:
print(response)
if not self.runStatus:
sys.exit(0)
if response.code != "000000":
self.runStatus = False
sys.exit(0)
except Exception:
print("err")


if __name__ == '__main__':
client = avatarClient()
client.serverUrl = "xxx.xxx.xxx.xxx:xxxx"
client.start()

5. 打造自己的测试工具

在编辑器中执行测试,有时候交互性不太友好,因此我们可以打造一个带交互界面的测试工具。QT是跨平台C++库的集合,它实现高级API来访问现代桌面和移动系统的许多方面。这些服务包括定位和定位服务、多媒体、NFC和蓝牙连接、基于铬的web浏览器以及传统的UI开发。PyQt5是一套针对QtV5的全面Python绑定。它被实现为超过35个扩展模块,并使Python可以作为一个替代的应用程序开发语言C++在所有支持的平台上包括IOS和Android。

5.1 安装PyQt5

pip install PyQt5

如果要使用图像界面进行设计,可以安装Qt Designer图形界面开发工具,相关配置可以自行搜索。

pip install PyQt5-tools

5.2 打造websocket测试工具

下面以websocket接口为例,实现一个nlp的测试工具

# -*- coding: utf-8 -*-
import sys
import asyncio
import base64
import time
import uuid
import websockets
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *


class Ui_mainWindow(object):
def __init__(self, mainWindow):
self.mainWindow = mainWindow
self.setupUi()

def setupUi(self):
self.mainWindow.setObjectName("mainWindow")
self.mainWindow.setWindowModality(QtCore.Qt.WindowModal)
self.mainWindow.resize(600, 300)
self.mainWindow.setWindowTitle("NLP测试工具")

self.centralwidget = QtWidgets.QWidget(self.mainWindow)
self.centralwidget.setObjectName("centralwidget")

self.widget1 = QtWidgets.QWidget(self.centralwidget)
self.widget1.setGeometry(QtCore.QRect(10, 30, 400, 25))
self.widget1.setObjectName("widget1")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget1)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")

self.serverUrlLabel = QtWidgets.QLabel(self.widget1)
self.serverUrlLabel.setObjectName("label")
self.serverUrlLabel.setText("服务地址:")
self.horizontalLayout.addWidget(self.serverUrlLabel)

self.serverUrlLineEdit = QtWidgets.QLineEdit(self.widget1)
self.serverUrlLineEdit.setEnabled(True)
self.serverUrlLineEdit.setText("ws://xxx..xxx.xxx/nlp")
self.serverUrlLineEdit.setMinimumWidth(320)
self.serverUrlLineEdit.setMaximumWidth(320)
self.serverUrlLineEdit.setObjectName("serverUrlLineEdit")
self.horizontalLayout.addWidget(self.serverUrlLineEdit, stretch=500, alignment=QtCore.Qt.AlignLeft)

self.sendTextWidget = QtWidgets.QWidget(self.centralwidget)
self.sendTextWidget.setGeometry(QtCore.QRect(0, 70, 500, 70))
self.sendTextWidget.setObjectName("sendTextWidget")
self.sendTextLayout = QtWidgets.QHBoxLayout(self.sendTextWidget)
self.sendTextLayout.setContentsMargins(0, 0, 0, 0)
self.sendTextLayout.setObjectName("sendTextLayout")

self.sendTextLabel = QtWidgets.QLabel(self.sendTextWidget)
self.sendTextLabel.setContentsMargins(20, 0, 0, 0)
self.sendTextLabel.setText("文本:")
self.sendTextLayout.addWidget(self.sendTextLabel)

self.sendTextTextEdit = QtWidgets.QTextEdit(self.sendTextWidget)
self.sendTextTextEdit.setObjectName("sendTextTextEdit")
self.sendTextLayout.addWidget(self.sendTextTextEdit)

self.sendTextButton = QtWidgets.QPushButton(self.sendTextWidget)
self.sendTextButton.setObjectName("sendText")
self.sendTextButton.setText("发送")
self.sendTextButton.clicked.connect(self.send_text)
self.sendTextLayout.addWidget(self.sendTextButton)

self.widget3 = QtWidgets.QWidget(self.centralwidget)
self.widget3.setGeometry(QtCore.QRect(0, 160, 420, 90))
self.widget3.setObjectName("widget3")

self.logLayout = QtWidgets.QHBoxLayout(self.widget3)
self.logLayout.setContentsMargins(0, 0, 0, 0)
self.logLayout.setObjectName("logLayout")

self.logLabel = QtWidgets.QLabel(self.widget3)
self.logLabel.setObjectName("logLabel")
self.logLabel.setContentsMargins(20, 0, 0, 0)
self.logLabel.setLineWidth(30)
self.logLabel.setText("返回:")
self.logLayout.addWidget(self.logLabel)

self.logTextEdit = QtWidgets.QTextEdit(self.widget3)
self.logTextEdit.setContentsMargins(0, 0, 0, 0)
self.logTextEdit.setObjectName("logTextEdit")
self.logLayout.addWidget(self.logTextEdit)

self.mainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(self.mainWindow)
self.statusbar.setObjectName("statusbar")
self.mainWindow.setStatusBar(self.statusbar)

QtCore.QMetaObject.connectSlotsByName(self.mainWindow)

def send_text(self):
self.websocketClient = WebsocketClient()
self.websocketClient.url = self.serverUrlLineEdit.text()
self.websocketClient.text = self.sendTextTextEdit.toPlainText()
result = self.websocketClient.run()
self.logTextEdit.setText(result)
class WebsocketClient:
def __init__(self):
self.url = ""

async def send_msg(self, websocket):
if self.text == "":
return "empty text"
bs = str(base64.b64encode(self.text.encode('utf-8')), 'utf-8')
sid = uuid.uuid4()
timestamp = str(int(time.time()) * 1000)
msg = '{"app":"test","sn":"123","timeStamp":"' + timestamp + '","version":"1.0.0","data":"' + bs + '",' \
'"sid":"' + str(sid) + '"} '
await websocket.send(msg)
rev_text = await websocket.recv()
self.result = rev_text
self.text = ""
return rev_text

async def connect(self):
try:
async with websockets.connect(self.url) as websocket:
res = await self.send_msg(websocket)
return res
except Exception as e:
return str(e)

def run(self):
return asyncio.get_event_loop().run_until_complete(self.connect())


if __name__ == "__main__":
app = QApplication(sys.argv)
window = QMainWindow()
box = Ui_mainWindow(window)
window.show()
sys.exit(app.exec_())

执行结果:

Python在接口测试中的应用_测试工具

5.3 虚拟主播工具介绍

上一节中,介绍了虚拟主播服务grpc接口示例,那么可以使用PyQt5打造虚拟主播的测试工具,此处不再提供示例代码,运行如下图:

Python在接口测试中的应用_测试工具_02

标签:__,Python,text,self,接口,测试,time,type,def
From: https://blog.51cto.com/u_15641375/5807578

相关文章

  • APP自动化效果测试工具
    ​1.背景项目测试过程中经常需要在手机端体验语音产品的识别效果和稳定性,识别效果与手机硬件强相关无法抛开硬件影响。因此开发了一套基于uiautomator2+pythonUI自动化工......
  • Python接入微信公众号Token验证
    注意点官方示例是Pthon2版本的,如果是Python3版本需要有改动验证成功返回echostr要是数字格式的公众号侧配置(公众号后台-基本配置)服务器侧配置代码部分......
  • SpringBoot 阶段测试 1
    SpringBoot阶段测试1目录SpringBoot阶段测试11、使用JDK8新语法完成下列集合练习:1.1List中有1,2,3,4,5,6,7,8,9几个元素要求;(1)将奇、偶数分别汇聚成一个List(2)分别求......
  • python周结
    本周内容总结1.正则表达式1.1正则表达式之字符组'''字符组默认匹配方式是挨个挨个匹配'''[0123456789] 匹配0到9任意一个数(全写)[0-9] 匹配0到9任意一个数(......
  • python虚拟环境
    python虚拟环境python-mvenvvenvdemocdvenvdemodircdLibactivatepython显示环境变量echo%PATH%importsysfrompprintimportpprintpprint(sys.path)......
  • Python学习日报
    2022.10.30重新学习Python的第一天1.Python中使用缩进来表示代码块,统一代码块中应使用相同数量的空格2.Python中使用#对文中代码进行注释,或者使用""""""来表示多行......
  • 测试分析-网络分析
    一、TTL与DNSTTL全称为timetolive,即生存时间。TTL的最大值是255,一般推荐值是64。TTL是IP数据包在计算机网络中存在的时间。实际上TTL是IP数据包在计算机网络中可以转发的......
  • Python程序员常犯的编码错误(三)
    1.引言本文是Python程序员常犯的编码错误的第三篇,在前两篇中我们重点介绍了常见的几种错误,本文继续介绍该话题,希望大家在日常生活中多多关注。闲话少说,我们直接开始吧!2.使......
  • [python]小白尝试播放某云vip歌曲
    尝试一下能不能将某云上的vip歌曲下载到本地并且能够正常播放首先附上代码:importrequestsurl="https://music.163.com/weapi/cloudsearch/get/web?csrf_token="dat......
  • python 笔记
    虚拟环境创建虚拟环境python-mvenvenv_name激活虚拟环境进入虚拟环境路径下的script目录,执行activatecdE:\env\test_env\scripts./activate 按requiremen......