WebsocketTest 1.0.4__tar.gz → 1.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {websockettest-1.0.4 → websockettest-1.0.6}/PKG-INFO +1 -1
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/caseScript/Aqua.py +2 -5
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/caseScript/Gateway.py +4 -4
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/cli.py +1 -1
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/commands/test.py +1 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/common/WSBaseApi.py +2 -1
- websockettest-1.0.6/WebsocketTest/common/logger.py +14 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/common/utils.py +2 -3
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/conftest.py +1 -5
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/run_tests.py +13 -10
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest.egg-info/PKG-INFO +1 -1
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest.egg-info/SOURCES.txt +0 -1
- {websockettest-1.0.4 → websockettest-1.0.6}/setup.py +4 -4
- websockettest-1.0.4/WebsocketTest/common/WebSocketApi.py +0 -73
- websockettest-1.0.4/WebsocketTest/common/logger.py +0 -27
- {websockettest-1.0.4 → websockettest-1.0.6}/README.md +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/__init__.py +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/caseScript/__init__.py +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/commands/__init__.py +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/commands/startproject.py +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/common/Assertion.py +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/common/__init__.py +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest/common/assertUtils.py +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest.egg-info/dependency_links.txt +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest.egg-info/entry_points.txt +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest.egg-info/requires.txt +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/WebsocketTest.egg-info/top_level.txt +0 -0
- {websockettest-1.0.4 → websockettest-1.0.6}/setup.cfg +0 -0
@@ -4,9 +4,6 @@ from urllib.parse import quote_plus
|
|
4
4
|
from WebsocketTest.common import WSBaseApi
|
5
5
|
from WebsocketTest.common.WSBaseApi import WSBaseApi
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
7
|
class ApiTestRunner(WSBaseApi):
|
11
8
|
def __init__(self, **kwargs):
|
12
9
|
super().__init__(**kwargs)
|
@@ -145,7 +142,7 @@ class ApiTestRunner(WSBaseApi):
|
|
145
142
|
msg = json.loads(_msg)
|
146
143
|
code = safe_get(msg, ["header","code"])
|
147
144
|
if code != 0:
|
148
|
-
|
145
|
+
logger.error(f'请求错误: {code}, {msg}')
|
149
146
|
break
|
150
147
|
else:
|
151
148
|
answer = safe_get(msg, ["payload","results","text","intent","answer"])
|
@@ -159,7 +156,7 @@ class ApiTestRunner(WSBaseApi):
|
|
159
156
|
return
|
160
157
|
|
161
158
|
except Exception as e:
|
162
|
-
|
159
|
+
logger.error(f"error in handle_v1_chain :{e}")
|
163
160
|
break
|
164
161
|
|
165
162
|
|
@@ -66,7 +66,7 @@ class ApiTestRunner(WSBaseApi):
|
|
66
66
|
while True:
|
67
67
|
try:
|
68
68
|
msg = await ws.recv()
|
69
|
-
print(msg)
|
69
|
+
# print(msg)
|
70
70
|
response_data = json.loads(msg)
|
71
71
|
# code 返回码,0表示成功,其它表示异常
|
72
72
|
if response_data["header"]["code"] == 0:
|
@@ -81,10 +81,10 @@ class ApiTestRunner(WSBaseApi):
|
|
81
81
|
elif status == 2:
|
82
82
|
break
|
83
83
|
else:
|
84
|
-
|
84
|
+
logger.error(f"返回结果错误:{response_data['header']['message']}")
|
85
85
|
break
|
86
86
|
except Exception as e:
|
87
|
-
|
87
|
+
logger.error(f"Error in processing message: {e}")
|
88
88
|
break
|
89
89
|
# @exception_decorator
|
90
90
|
async def handle_v1_chain(self, ws):
|
@@ -113,7 +113,7 @@ class ApiTestRunner(WSBaseApi):
|
|
113
113
|
self.response = json.loads(data['content'])
|
114
114
|
return
|
115
115
|
except Exception as e:
|
116
|
-
|
116
|
+
logger.error(f"error in handle_v1_chain :{e}")
|
117
117
|
break
|
118
118
|
|
119
119
|
def build_params(self,chain=None):
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
3
3
|
from importlib import import_module
|
4
4
|
|
5
5
|
def main():
|
6
|
-
parser = argparse.ArgumentParser(description="
|
6
|
+
parser = argparse.ArgumentParser(description="WebSocket Test CLI")
|
7
7
|
subparsers = parser.add_subparsers(dest='command', required=True)
|
8
8
|
|
9
9
|
# 动态加载子命令
|
@@ -10,6 +10,7 @@ def configure_parser(parser):
|
|
10
10
|
parser.add_argument("--project", required=True, help="Project name")
|
11
11
|
parser.add_argument("--port", type=int, default=8883, help="Allure report port")
|
12
12
|
parser.add_argument("--report-dir", default="allure_report", help="Allure report directory")
|
13
|
+
parser.add_argument("--testcase", required=False, help='Specify the test case to run (e.g., "testcase/test_all.py::TestAqua::test_api[case_suite0]"')
|
13
14
|
|
14
15
|
def execute(args):
|
15
16
|
"""执行test"""
|
@@ -49,9 +49,10 @@ class BaseApiTest:
|
|
49
49
|
f"无法加载 {module_path}.ApiTestRunner,"
|
50
50
|
"请检查模块路径和类命名是否符合规范"
|
51
51
|
) from e
|
52
|
+
|
52
53
|
|
53
54
|
@pytest.mark.parametrize('case_suite', gen_case_suite(CASE_PATH))
|
54
|
-
def
|
55
|
+
def test(self, case_suite, setup_env):
|
55
56
|
"""测试用例执行模板"""
|
56
57
|
try:
|
57
58
|
# 1. 合并参数
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
# 配置全局日志记录设置
|
4
|
+
# 配置日志记录
|
5
|
+
logging.basicConfig(
|
6
|
+
level=logging.INFO,
|
7
|
+
format='%(asctime)s.%(msecs)03d - %(levelname)s - %(name)s - %(message)s',
|
8
|
+
datefmt='%H:%M:%S',
|
9
|
+
handlers=[
|
10
|
+
logging.StreamHandler(), # 输出到控制台
|
11
|
+
]
|
12
|
+
)
|
13
|
+
# 创建一个记录器实例
|
14
|
+
logger = logging.getLogger()
|
@@ -6,9 +6,8 @@ import string
|
|
6
6
|
from datetime import datetime
|
7
7
|
import email.utils
|
8
8
|
from functools import wraps
|
9
|
-
from WebsocketTest.common.logger import
|
9
|
+
from WebsocketTest.common.logger import logger
|
10
10
|
from typing import Optional, Union, Literal
|
11
|
-
import numpy as np
|
12
11
|
def get_rfc1123_time():
|
13
12
|
# 获取当前UTC时间
|
14
13
|
now = datetime.utcnow()
|
@@ -208,7 +207,7 @@ def exception_decorator(func):
|
|
208
207
|
function_name = func.__name__
|
209
208
|
file_name = os.path.basename(func.__code__.co_filename) # 提取文件名
|
210
209
|
# 打印异常和函数名
|
211
|
-
|
210
|
+
logger.error( f"异常发生在文件 [{file_name}] 的函数 [{function_name}] 中: {str(e)}",
|
212
211
|
exc_info=True # 自动追加堆栈信息
|
213
212
|
)
|
214
213
|
# 可选择再次抛出异常或进行其他处理
|
@@ -1,13 +1,12 @@
|
|
1
1
|
import subprocess
|
2
2
|
import argparse
|
3
3
|
import shutil
|
4
|
-
from WebsocketTest.common.logger import *
|
5
4
|
import time
|
6
5
|
import webbrowser
|
7
6
|
from urllib.request import urlopen
|
8
7
|
from urllib.error import URLError
|
9
|
-
logger = logging.getLogger('run_tests')
|
10
8
|
from pathlib import Path
|
9
|
+
from WebsocketTest.common.logger import logger
|
11
10
|
|
12
11
|
class AllureManager:
|
13
12
|
def __init__(self, port: int = 8883):
|
@@ -28,7 +27,7 @@ class AllureManager:
|
|
28
27
|
"""启动Allure服务"""
|
29
28
|
try:
|
30
29
|
cmd = [self.allure_path, "open", report_dir, "-p", str(self.port)]
|
31
|
-
logger.info(f"start_server Executing: {' '.join(cmd)}")
|
30
|
+
# logger.info(f"start_server Executing: {' '.join(cmd)}")
|
32
31
|
subprocess.Popen(
|
33
32
|
cmd,
|
34
33
|
stdout=subprocess.DEVNULL,
|
@@ -72,20 +71,23 @@ class TestRunner:
|
|
72
71
|
self.allure_results = str(Path.cwd().joinpath("allure_results"))
|
73
72
|
|
74
73
|
def run_pytest_tests(self) -> bool:
|
75
|
-
"""执行pytest测试"""
|
76
|
-
|
77
|
-
|
74
|
+
"""执行pytest测试"""
|
75
|
+
# 构建基础命令列表
|
78
76
|
cmd = [
|
79
|
-
"pytest",
|
80
|
-
"-m",
|
77
|
+
"pytest",
|
78
|
+
"-m", self.args.service.split('_')[0],
|
81
79
|
"--env", self.args.env,
|
82
80
|
"--app", self.args.app,
|
83
81
|
"--service", self.args.service,
|
84
82
|
"--project", self.args.project,
|
85
83
|
"--alluredir", self.allure_results
|
86
84
|
]
|
85
|
+
# 添加可选测试路径(如果存在)
|
86
|
+
if hasattr(self.args, 'testcase') and self.args.testcase:
|
87
|
+
cmd.insert(1, self.args.testcase)
|
88
|
+
print(f"run_pytest_tests Executing: {' '.join(cmd)}")
|
87
89
|
try:
|
88
|
-
logger.info(f"run_pytest_tests Executing: {' '.join(cmd)}")
|
90
|
+
# logger.info(f"run_pytest_tests Executing: {' '.join(cmd)}")
|
89
91
|
subprocess.run(cmd, check=True, timeout=3600)
|
90
92
|
except subprocess.CalledProcessError as e:
|
91
93
|
logger.error(f"Tests failed with exit code {e.returncode}")
|
@@ -101,7 +103,7 @@ class TestRunner:
|
|
101
103
|
check=True,
|
102
104
|
timeout=300
|
103
105
|
)
|
104
|
-
logger.info(f"generate_allure_report Executing: {' '.join(cmd)}")
|
106
|
+
# logger.info(f"generate_allure_report Executing: {' '.join(cmd)}")
|
105
107
|
except subprocess.CalledProcessError as e:
|
106
108
|
logger.error(f"Report generation failed: {e}")
|
107
109
|
def _handle_allure_report(self) -> bool:
|
@@ -136,6 +138,7 @@ if __name__ == "__main__":
|
|
136
138
|
parser.add_argument("--project", required=True, help="Project name")
|
137
139
|
parser.add_argument("--port", type=int, default=8883, help="Allure report port")
|
138
140
|
parser.add_argument("--report-dir", default="allure_report", help="Allure report directory")
|
141
|
+
parser.add_argument("--testcase", required=False, help='Specify the test case to run (e.g., "testcase/test_all.py::TestAqua::test_api[case_suite0]"')
|
139
142
|
args = parser.parse_args()
|
140
143
|
test_runner = TestRunner(args)
|
141
144
|
exit(test_runner.run())
|
@@ -19,7 +19,6 @@ WebsocketTest/commands/startproject.py
|
|
19
19
|
WebsocketTest/commands/test.py
|
20
20
|
WebsocketTest/common/Assertion.py
|
21
21
|
WebsocketTest/common/WSBaseApi.py
|
22
|
-
WebsocketTest/common/WebSocketApi.py
|
23
22
|
WebsocketTest/common/__init__.py
|
24
23
|
WebsocketTest/common/assertUtils.py
|
25
24
|
WebsocketTest/common/logger.py
|
@@ -18,7 +18,7 @@ setup(
|
|
18
18
|
'bdist_wheel': CustomBdistWheel
|
19
19
|
},
|
20
20
|
name="WebsocketTest",
|
21
|
-
version="1.0.
|
21
|
+
version="1.0.6",
|
22
22
|
author='chencheng',
|
23
23
|
python_requires=">=3.10",
|
24
24
|
packages=find_packages(exclude=["WebsocketTest.allure_report", "WebsocketTest.logs", "WebsocketTest.allure_results", "WebsocketTest.config", "WebsocketTest.data","WebsocketTest.testcase"]),
|
@@ -37,7 +37,7 @@ setup(
|
|
37
37
|
]
|
38
38
|
}
|
39
39
|
)
|
40
|
-
import shutil
|
40
|
+
# import shutil
|
41
41
|
|
42
|
-
# 清理 .egg-info 文件夹
|
43
|
-
shutil.rmtree('WebsocketTest.egg-info', ignore_errors=True)
|
42
|
+
# # 清理 .egg-info 文件夹
|
43
|
+
# shutil.rmtree('WebsocketTest.egg-info', ignore_errors=True)
|
@@ -1,73 +0,0 @@
|
|
1
|
-
import _thread as thread
|
2
|
-
import logging
|
3
|
-
import websocket # 使用websocket_client
|
4
|
-
from WebsocketTest.common.utils import *
|
5
|
-
|
6
|
-
class WebSocketApi:
|
7
|
-
def __init__(self, url, request):
|
8
|
-
self.url = url
|
9
|
-
self.request = request
|
10
|
-
self.answer_text = ""
|
11
|
-
self.errcode = ""
|
12
|
-
self.response = {}
|
13
|
-
self.ws = None
|
14
|
-
|
15
|
-
def on_error(self, ws, error):
|
16
|
-
"""处理WebSocket错误"""
|
17
|
-
logging.error(f"### error: {error}")
|
18
|
-
self.errcode = str(error)
|
19
|
-
self.ws.close()
|
20
|
-
|
21
|
-
def on_close(self, ws, close_status_code, close_msg):
|
22
|
-
"""处理WebSocket关闭"""
|
23
|
-
logging.info(f"### ws closed with status {close_status_code} and message {close_msg}")
|
24
|
-
|
25
|
-
def on_open(self, ws):
|
26
|
-
"""处理WebSocket连接建立"""
|
27
|
-
thread.start_new_thread(self.run, (ws,))
|
28
|
-
|
29
|
-
def run(self, ws, *args):
|
30
|
-
"""发送请求"""
|
31
|
-
ws.send(self.request)
|
32
|
-
|
33
|
-
def on_message(self, ws, message: str):
|
34
|
-
"""处理WebSocket消息"""
|
35
|
-
try:
|
36
|
-
msg = json.loads(message)
|
37
|
-
code = safe_get(msg, ["header","code"])
|
38
|
-
if code != 0:
|
39
|
-
logging.error(f'请求错误: {code}, {msg}')
|
40
|
-
err_msg = safe_get(msg, ["header","message"])
|
41
|
-
self.errcode = f"{code}, error msg: {err_msg}"
|
42
|
-
self.ws.close()
|
43
|
-
else:
|
44
|
-
answer = safe_get(msg, ["payload","results","text","intent","answer"])
|
45
|
-
answerText = safe_get(answer, ["text"])
|
46
|
-
if answerText:
|
47
|
-
self.answer_text += answerText
|
48
|
-
if msg['header']['status']=="2" or msg['header']['status']=="3": # 返回结果接收完成
|
49
|
-
if self.answer_text:
|
50
|
-
answer["text"] = self.answer_text
|
51
|
-
self.response = msg
|
52
|
-
self.ws.close()
|
53
|
-
except json.JSONDecodeError as e:
|
54
|
-
logging.error(f"JSON解码错误: {e}")
|
55
|
-
self.errcode = f"JSON解码错误: {e}"
|
56
|
-
self.ws.close()
|
57
|
-
|
58
|
-
def start(self):
|
59
|
-
"""启动WebSocket客户端"""
|
60
|
-
websocket.enableTrace(False)
|
61
|
-
self.ws = websocket.WebSocketApp(self.url,
|
62
|
-
on_open=self.on_open,
|
63
|
-
on_error=self.on_error,
|
64
|
-
on_message=self.on_message,
|
65
|
-
on_close=self.on_close)
|
66
|
-
self.ws.run_forever()
|
67
|
-
|
68
|
-
|
69
|
-
def main(Spark_url, request: str):
|
70
|
-
"""主函数,启动WebSocket客户端并返回响应"""
|
71
|
-
client = WebSocketApi(Spark_url, request)
|
72
|
-
client.start()
|
73
|
-
return client.response
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import logging
|
3
|
-
from datetime import datetime
|
4
|
-
|
5
|
-
def configure_logging():
|
6
|
-
# 指定日志文件夹路径
|
7
|
-
log_dir = 'logs'
|
8
|
-
|
9
|
-
# 创建日志文件夹(如果它不存在)
|
10
|
-
os.makedirs(log_dir, exist_ok=True)
|
11
|
-
|
12
|
-
# 获取今天的日期,用于日志文件名
|
13
|
-
today_date = datetime.now().date()
|
14
|
-
|
15
|
-
# 配置日志记录
|
16
|
-
logging.basicConfig(
|
17
|
-
level=logging.INFO,
|
18
|
-
format='%(asctime)s.%(msecs)03d - %(levelname)s - %(name)s - %(message)s',
|
19
|
-
datefmt='%H:%M:%S',
|
20
|
-
handlers=[
|
21
|
-
logging.StreamHandler(), # 输出到控制台
|
22
|
-
logging.FileHandler(f'{log_dir}/{today_date}.log') # 输出到文件
|
23
|
-
]
|
24
|
-
)
|
25
|
-
|
26
|
-
# 调用函数以配置日志记录
|
27
|
-
configure_logging()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|