Применение Python при тестировании интерфейса
Применение Python при тестировании интерфейса

1. Введение

Существует множество способов тестирования интерфейсов. В число инструментов, которые вы можете использовать, входят 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 для создания собственных инструментов тестирования.

2. Интерфейс протокола http

Для интерфейса протокола http удобнее всего использовать библиотеку запросов, поэтому для тестирования интерфейса протокола http используется библиотека запросов. Запросы на установку:

Язык кода:javascript
копировать
pip install requests

2.1 Пример GET-запроса

Интерфейс запроса погоды:http://wthrcdn.etouch.cn/weather_mini

Язык кода:javascript
копировать
import requests
r = requests.get('http://wthrcdn.etouch.cn/weather_mini')
print(r.text)

Результат вывода: '{"status":1002,"desc":"invilad-citykey"}'

2.2 Пример GET-запроса с параметрами

Параметры: город название города

Язык кода:javascript
копировать
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 значения города.

Язык кода:javascript
копировать
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"}'

2.3 Пример POST-запроса

В этом примере используется пример запросов с официального сайта. POST-запросы в дальнейшем не будут представлены. См. официальный сайт. Github API v3 принимает данные POST в формате JSON

Язык кода:javascript
копировать
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))

3. Интерфейс протокола Websocket.

Установить библиотеку веб-сокетов

Язык кода:javascript
копировать
pip install websockets

Ниже приведен пример интерфейса NLP. Клиент подключается к серверу, отправляет текст и получает возвращаемый результат. Текст должен быть зашифрован в формате Base64.

Язык кода:javascript
копировать
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}

4. интерфейс протокола grpc

Для протокола grpc требуется Python версии 3.5 или выше. Установите необходимые библиотеки:

Язык кода:javascript
копировать
pip install grpcio
pip install grpcio-tools

В качестве примера возьмем интерфейс службы виртуальной привязки. Служба использует двунаправленный поток grpc для взаимодействия. После установления соединения с сервером она возвращает rtmp-адрес, отправляет видеопоток виртуальной привязки, отправляет текст на сервер и едет. виртуальный якорь для трансляции текста.

4.1 Запись файла avatar.proto

Язык кода:javascript
копировать
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

Вставьте два вышеуказанных файла в код проекта.

Язык кода:javascript
копировать
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()

5. Создайте свои собственные инструменты тестирования

Выполнение тестов в редакторе иногда не очень интерактивно, поэтому мы можем создать инструмент тестирования с интерактивным интерфейсом. QT — это набор кроссплатформенных библиотек C++, которые реализуют высокоуровневые API для доступа ко многим аспектам современных настольных и мобильных систем. Эти услуги включают в себя определение местоположения и службы определения местоположения, мультимедиа, подключение NFC и Bluetooth, веб-браузеры на базе Chromium и разработку традиционных пользовательских интерфейсов. PyQt5 — это полный набор привязок Python для QtV5. Он реализован в виде более чем 35 модулей расширения и позволяет использовать Python в качестве языка разработки приложений, альтернативного C++, на всех поддерживаемых платформах, включая iOS и Android.

5.1 Установите PyQt5

Язык кода:javascript
копировать
pip install PyQt5

Если вы хотите использовать графический интерфейс для проектирования, вы можете установить инструмент разработки графического интерфейса Qt Designer и самостоятельно искать соответствующие конфигурации.

Язык кода:javascript
копировать
pip install PyQt5-tools

5.2 Создание инструментов тестирования веб-сокетов

Ниже в качестве примера для реализации инструмента тестирования nlp используется интерфейс веб-сокета.

Язык кода:javascript
копировать
# -*- 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)
Язык кода:javascript
копировать
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 можно использовать для создания инструмента тестирования виртуальной привязки. Пример кода здесь больше не представлен.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose