Существует множество способов тестирования интерфейсов. В число инструментов, которые вы можете использовать, входят jmeter, postman, SoapUI и т. д. Вы также можете написать собственный код для тестирования интерфейсов (Python, Java, Go и т. д.). Использование инструментов относительно просто. , и его можно использовать прямо из коробки. Но если интерфейс определяет какие-то динамические вычисления, требующие шифрования, дешифрования, цифровых подписей и т. д., инструмент беспомощен, и единственный выход — написать код для тестирования реализации. Поэтому инструменты необходимо выбирать целенаправленно на основе протокола интерфейса. Когда инструмент не подходит для проекта, требуется его разработка. Когда дело доходит до выбора языка для разработки инструментов, сам язык не имеет преимуществ или недостатков. Выбирайте то, в чем вы хороши и что подходит. По сравнению с языками Java и Go, Python не требует компиляции и поддерживает множество библиотек. Это его особенность; он поддерживает интерфейсы протокола http, такие как urllib, urllib2 и библиотеку запросов, а библиотеки, поддерживающие протокол веб-сокетов, включают веб-сокеты, веб-сокет-клиент и grpc. Библиотеки включают grpcio, grpcio-tools и PyQt5, поддерживающий графический интерфейс. Версия Python, используемая в этой статье, — 3.9.0. Ниже приводится краткое введение в примеры интерфейсов http, websocket и grpc и, наконец, рассказывается об использовании PyQt5 для создания собственных инструментов тестирования.
Для интерфейса протокола http удобнее всего использовать библиотеку запросов, поэтому для тестирования интерфейса протокола http используется библиотека запросов. Запросы на установку:
pip install requests
Интерфейс запроса погоды: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"}'
Параметры: город название города
import requests
data ={}
data['city']='Пекин'
r = requests.get('http://wthrcdn.etouch.cn/weather_mini',params=data)
print(r.text)
Результаты вывода: '{"data":{"вчера":{"date":"Вторник, 31 число","high":"Высокая температура 27℃","fx":"Южный ветер","низкий": "Низкая температура 17℃","fl":"","type":"Легкий дождь"},"city":"Пекин","forecast":[{"date":"Среда, 1-го числа","высокая ":"Высокая температура 29℃","fengli":"","low":"низкая температура 18℃","fengxiang":"южный ветер","type":"ясно"},{"date":"Четверг, 2-е" , «высокий»: «Высокая температура 30 ℃», «fengli»: «», «низкий»: «Низкая температура 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":" Dongfeng","type":"небольшой дождь"}],"ganmao":"Выходя на улицу, поправляйте одежду и обращайте внимание на уровень увлажнения.","wendu":"23"},"status":1000, "desc":"ОК"}'
Если служба проверяет согласованность города в запросе, авторизацию необходимо передать в заголовке, который представляет собой 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":{"вчера":{"date":"Вторник, 31-е","high":"Высокая температура 35℃","fx":"Южный ветер","low":" Низкая температура 25℃","fl":"","type":"ясно"},"city":"Хэфэй","forecast":[{"date":"Среда, 1-е","high": «Высокая температура 30℃","fengli":"","low":"низкая температура 24℃","fengxiang":"северный ветер","type":"легкий дождь"},{"date":"Четверг, 2-е число ", "высокий":"Высокая температура 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"}'
В этом примере используется пример запросов с официального сайта. POST-запросы в дальнейшем не будут представлены. См. официальный сайт. Github API v3 принимает данные POST в формате JSON
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
Установить библиотеку веб-сокетов
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":"d28c76 31-54d9-493e-8db8-f67a5ecc2a25","text":"Я хочу проверить баланс",,"semantic":[{"intent":"querybalance","in tentName":"Баланс запроса","intentCnxt":"","template":"{Query}Balance","score":0.865519,"slots":[]}],"di alog":{"status":0,"uid":"","reaction":{"text":""},"slots":null},"answer":{"answerType":"" ,"text":"","emotion":"","topic":"","topicID":"","type":"","question":{"question":"","ques tion_ws":""}}}","extendData":"","sid":"d28c7631-54d9-493e-8db8-f67a5ecc2a25","last":true}
Для протокола grpc требуется Python версии 3.5 или выше. Установите необходимые библиотеки:
pip install grpcio
pip install grpcio-tools
В качестве примера возьмем интерфейс службы виртуальной привязки. Служба использует двунаправленный поток grpc для взаимодействия. После установления соединения с сервером она возвращает rtmp-адрес, отправляет видеопоток виртуальной привязки, отправляет текст на сервер и едет. виртуальный якорь для трансляции текста.
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) {
}
}
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out= ./avatar.proto наконец генерирует два файла avatar_pb2.py и avatar_pb2_grpc.py.
Вставьте два вышеуказанных файла в код проекта.
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'))
# отправить пинг
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,тип = self.pingType)
защита send_message (сам):
дать 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()
Выполнение тестов в редакторе иногда не очень интерактивно, поэтому мы можем создать инструмент тестирования с интерактивным интерфейсом. QT — это набор кроссплатформенных библиотек C++, которые реализуют высокоуровневые API для доступа ко многим аспектам современных настольных и мобильных систем. Эти услуги включают в себя определение местоположения и службы определения местоположения, мультимедиа, подключение NFC и Bluetooth, веб-браузеры на базе Chromium и разработку традиционных пользовательских интерфейсов. PyQt5 — это полный набор привязок Python для QtV5. Он реализован в виде более чем 35 модулей расширения и позволяет использовать Python в качестве языка разработки приложений, альтернативного C++, на всех поддерживаемых платформах, включая iOS и Android.
pip install PyQt5
Если вы хотите использовать графический интерфейс для проектирования, вы можете установить инструмент разработки графического интерфейса Qt Designer и самостоятельно искать соответствующие конфигурации.
pip install PyQt5-tools
Ниже в качестве примера для реализации инструмента тестирования 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("Инструмент тестирования НЛП")
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_())
Результат выполнения:
В предыдущем разделе был представлен пример интерфейса grpc службы виртуальной привязки. Затем PyQt5 можно использовать для создания инструмента тестирования виртуальной привязки. Пример кода здесь больше не представлен.