Python在接口测试中的应用

本文涉及的产品
NLP 自学习平台,3个模型定制额度 1个月
NLP自然语言处理_基础版,每接口每天50万次
NLP自然语言处理_高级版,每接口累计50万次
简介: 接口测试的方式有很多,可以使用的工具有jmeter,postman,soapUI等,也可以自己写代码进行接口测试(Python,java,go等等),工具的使用相对来说都比较简单,开箱即用。但如果接口中定义了一些需要加解密、数字签名等一些动态计算时,工具就很无助,唯有写代码进行实现测试。所以要根据接口协议,有针对性的进行选择工具,当工具不适合项目时需要进行工具开发。对于工具开发选择语言,语言本身没有优劣之分,选择自己擅长的和合适的。相对于java,go语言,Python不需要编译,而且支持的库很多,是其特点;其支持http协议接口的有urllib,urllib2以及requests库,支持we

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请求示例

天气查询接口:http://wthrcdn.etouch.cn/weather_mini

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_())

执行结果:

5.3 虚拟主播工具介绍

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

相关文章
|
1月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
10天前
|
算法 数据处理 Python
高精度保形滤波器Savitzky-Golay的数学原理、Python实现与工程应用
Savitzky-Golay滤波器是一种基于局部多项式回归的数字滤波器,广泛应用于信号处理领域。它通过线性最小二乘法拟合低阶多项式到滑动窗口中的数据点,在降噪的同时保持信号的关键特征,如峰值和谷值。本文介绍了该滤波器的原理、实现及应用,展示了其在Python中的具体实现,并分析了不同参数对滤波效果的影响。适合需要保持信号特征的应用场景。
59 11
高精度保形滤波器Savitzky-Golay的数学原理、Python实现与工程应用
|
15天前
|
IDE 测试技术 开发工具
10个必备Python调试技巧:从pdb到单元测试的开发效率提升指南
在Python开发中,调试是提升效率的关键技能。本文总结了10个实用的调试方法,涵盖内置调试器pdb、breakpoint()函数、断言机制、logging模块、列表推导式优化、IPython调试、警告机制、IDE调试工具、inspect模块和单元测试框架的应用。通过这些技巧,开发者可以更高效地定位和解决问题,提高代码质量。
123 8
10个必备Python调试技巧:从pdb到单元测试的开发效率提升指南
|
20天前
|
监控 JavaScript 测试技术
postman接口测试工具详解
Postman是一个功能强大且易于使用的API测试工具。通过详细的介绍和实际示例,本文展示了Postman在API测试中的各种应用。无论是简单的请求发送,还是复杂的自动化测试和持续集成,Postman都提供了丰富的功能来满足用户的需求。希望本文能帮助您更好地理解和使用Postman,提高API测试的效率和质量。
73 11
|
19天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
57 2
|
26天前
|
数据采集 存储 API
利用Python爬虫获取1688关键词接口全攻略
本文介绍如何使用Python爬虫技术合法合规地获取1688关键词接口数据,包括环境准备、注册1688开发者账号、获取Access Token、构建请求URL、发送API请求、解析HTML及数据处理存储等步骤,强调遵守法律法规和合理使用爬虫技术的重要性。
|
1月前
|
敏捷开发 测试技术 持续交付
自动化测试之美:从零开始搭建你的Python测试框架
在软件开发的马拉松赛道上,自动化测试是那个能让你保持节奏、避免跌宕起伏的神奇小助手。本文将带你走进自动化测试的世界,用Python这把钥匙,解锁高效、可靠的测试框架之门。你将学会如何步步为营,构建属于自己的测试庇护所,让代码质量成为晨跑时清新的空气,而不是雾霾中的忧虑。让我们一起摆脱手动测试的繁琐枷锁,拥抱自动化带来的自由吧!
|
1月前
|
缓存 开发者 Python
深入探索Python中的装饰器:原理、应用与最佳实践####
本文作为技术性深度解析文章,旨在揭开Python装饰器背后的神秘面纱,通过剖析其工作原理、多样化的应用场景及实践中的最佳策略,为中高级Python开发者提供一份详尽的指南。不同于常规摘要的概括性介绍,本文摘要将直接以一段精炼的代码示例开篇,随后简要阐述文章的核心价值与读者预期收获,引领读者快速进入装饰器的世界。 ```python # 示例:一个简单的日志记录装饰器 def log_decorator(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__} with args: {a
43 2
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
探索未来编程:Python在人工智能领域的深度应用与前景###
本文将深入探讨Python语言在人工智能(AI)领域的广泛应用,从基础原理到前沿实践,揭示其如何成为推动AI技术创新的关键力量。通过分析Python的简洁性、灵活性以及丰富的库支持,展现其在机器学习、深度学习、自然语言处理等子领域的卓越贡献,并展望Python在未来AI发展中的核心地位与潜在变革。 ###
|
13天前
|
存储 缓存 算法
探索企业文件管理软件:Python中的哈希表算法应用
企业文件管理软件依赖哈希表实现高效的数据管理和安全保障。哈希表通过键值映射,提供平均O(1)时间复杂度的快速访问,适用于海量文件处理。在Python中,字典类型基于哈希表实现,可用于管理文件元数据、缓存机制、版本控制及快速搜索等功能,极大提升工作效率和数据安全性。
49 0