VWED_server/tests/test_websocket_module.py

305 lines
11 KiB
Python
Raw Normal View History

2025-09-30 13:52:36 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
WebSocket模块测试
测试WebSocket内置函数的基本功能包括模拟WebSocket服务和客户端
"""
import asyncio
import json
import time
import threading
import sys
import os
from unittest.mock import Mock, AsyncMock, patch
from typing import Dict, Any, Set
# 添加项目根目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
if parent_dir not in sys.path:
sys.path.insert(0, parent_dir)
# 导入被测试的模块
try:
from services.online_script.built_in_modules.websocket_module import VWEDWebSocketModule
from utils.logger import get_logger
except ImportError as e:
print(f"导入项目模块失败: {e}")
print("请确保从项目根目录运行此脚本")
sys.exit(1)
logger = get_logger("tests.websocket_module")
class MockWebSocket:
"""模拟WebSocket连接"""
def __init__(self, client_ip: str, client_id: str = None):
self.client = Mock()
self.client.host = client_ip
self.client_id = client_id or f"client_{client_ip.replace('.', '_')}"
self.messages = []
self.closed = False
async def send_text(self, message: str):
"""模拟发送文本消息"""
if self.closed:
raise Exception("WebSocket已关闭")
self.messages.append(message)
logger.info(f"模拟WebSocket发送消息: {message}{self.client.host}")
def close(self):
"""关闭连接"""
self.closed = True
class MockConnectionManager:
"""模拟WebSocket连接管理器"""
def __init__(self):
self.active_connections: Dict[str, Set[MockWebSocket]] = {}
self.storage_location_connections: Dict[str, Set[MockWebSocket]] = {}
def add_connection(self, task_record_id: str, websocket: MockWebSocket):
"""添加活跃连接"""
if task_record_id not in self.active_connections:
self.active_connections[task_record_id] = set()
self.active_connections[task_record_id].add(websocket)
def add_storage_connection(self, scene_id: str, websocket: MockWebSocket):
"""添加库位状态连接"""
if scene_id not in self.storage_location_connections:
self.storage_location_connections[scene_id] = set()
self.storage_location_connections[scene_id].add(websocket)
async def send_personal_message(self, message: str, websocket: MockWebSocket):
"""发送个人消息"""
await websocket.send_text(message)
class WebSocketModuleTest:
"""WebSocket模块测试类"""
def __init__(self):
self.mock_manager = MockConnectionManager()
self.module = VWEDWebSocketModule("test_script_001")
# 设置模拟管理器
self.module._manager = self.mock_manager
def setup_test_connections(self):
"""设置测试连接"""
# 创建模拟WebSocket连接
self.ws1 = MockWebSocket("192.168.1.100", "client1")
self.ws2 = MockWebSocket("192.168.1.101", "client2")
self.ws3 = MockWebSocket("192.168.1.102", "client3")
# 添加到连接管理器
self.mock_manager.add_connection("task_001", self.ws1)
self.mock_manager.add_connection("task_002", self.ws2)
self.mock_manager.add_storage_connection("scene_001", self.ws3)
logger.info("测试连接设置完成")
async def test_send_msg_by_ip(self):
"""测试根据IP发送消息"""
logger.info("=== 测试根据IP发送消息 ===")
try:
# 测试发送消息到存在的IP
self.module.send_msg_to_wsc_by_client_ip("测试消息1", "192.168.1.100")
await asyncio.sleep(0.1) # 等待异步操作完成
# 检查消息是否发送
assert len(self.ws1.messages) > 0, "消息未发送到正确的WebSocket连接"
assert "测试消息1" in self.ws1.messages, "发送的消息内容不正确"
logger.info(f"✓ 成功发送消息到IP 192.168.1.100,收到消息: {self.ws1.messages}")
# 测试发送消息到不存在的IP
try:
self.module.send_msg_to_wsc_by_client_ip("测试消息2", "192.168.1.999")
assert False, "应该抛出异常但没有抛出"
except Exception as e:
logger.info(f"✓ 正确处理不存在的IP: {e}")
except Exception as e:
logger.error(f"✗ 测试根据IP发送消息失败: {e}")
raise
async def test_send_msg_by_name(self):
"""测试根据客户端名称发送消息"""
logger.info("=== 测试根据客户端名称发送消息 ===")
try:
# 测试发送消息到存在的客户端名称
self.module.send_msg_to_wsc_by_client_name("测试消息3", "task_001")
await asyncio.sleep(0.1) # 等待异步操作完成
# 检查消息是否发送
assert len(self.ws1.messages) > 1, "消息未发送到正确的WebSocket连接"
assert "测试消息3" in self.ws1.messages, "发送的消息内容不正确"
logger.info(f"✓ 成功发送消息到客户端 task_001收到消息: {self.ws1.messages}")
# 测试发送消息到不存在的客户端名称
try:
self.module.send_msg_to_wsc_by_client_name("测试消息4", "task_999")
assert False, "应该抛出异常但没有抛出"
except Exception as e:
logger.info(f"✓ 正确处理不存在的客户端名称: {e}")
except Exception as e:
logger.error(f"✗ 测试根据客户端名称发送消息失败: {e}")
raise
def test_get_client_ips(self):
"""测试获取客户端IP列表"""
logger.info("=== 测试获取客户端IP列表 ===")
try:
client_ips = self.module.get_websocket_client_ip()
# 验证结果
expected_ips = ["192.168.1.100", "192.168.1.101", "192.168.1.102"]
for ip in expected_ips:
assert ip in client_ips, f"IP {ip} 不在返回的列表中"
logger.info(f"✓ 成功获取客户端IP列表: {client_ips}")
except Exception as e:
logger.error(f"✗ 测试获取客户端IP列表失败: {e}")
raise
def test_get_client_names(self):
"""测试获取客户端名称列表"""
logger.info("=== 测试获取客户端名称列表 ===")
try:
client_names = self.module.get_websocket_client_name()
# 验证结果
expected_names = ["task_001", "task_002", "scene_001"]
for name in expected_names:
assert name in client_names, f"客户端名称 {name} 不在返回的列表中"
logger.info(f"✓ 成功获取客户端名称列表: {client_names}")
except Exception as e:
logger.error(f"✗ 测试获取客户端名称列表失败: {e}")
raise
async def test_error_handling(self):
"""测试错误处理"""
logger.info("=== 测试错误处理 ===")
try:
# 测试WebSocket连接异常
self.ws1.close()
try:
self.module.send_msg_to_wsc_by_client_ip("测试消息5", "192.168.1.100")
await asyncio.sleep(0.1)
logger.info("✓ 处理了WebSocket连接异常")
except Exception as e:
logger.info(f"✓ 正确捕获WebSocket异常: {e}")
except Exception as e:
logger.error(f"✗ 测试错误处理失败: {e}")
raise
async def run_all_tests(self):
"""运行所有测试"""
logger.info("开始WebSocket模块测试")
try:
# 设置测试环境
self.setup_test_connections()
# 运行测试
await self.test_send_msg_by_ip()
await self.test_send_msg_by_name()
self.test_get_client_ips()
self.test_get_client_names()
await self.test_error_handling()
logger.info("✓ 所有WebSocket模块测试通过")
except Exception as e:
logger.error(f"✗ WebSocket模块测试失败: {e}")
raise
def run_mock_websocket_server():
"""运行模拟WebSocket服务器"""
logger.info("=== 启动模拟WebSocket服务器 ===")
async def mock_server():
try:
# 创建测试实例
test = WebSocketModuleTest()
# 运行测试
await test.run_all_tests()
logger.info("模拟WebSocket服务器测试完成")
except Exception as e:
logger.error(f"模拟WebSocket服务器测试失败: {e}")
raise
# 运行异步测试
asyncio.run(mock_server())
def test_websocket_integration():
"""集成测试 - 模拟完整的WebSocket通信场景"""
logger.info("=== WebSocket集成测试 ===")
async def integration_test():
# 创建测试环境
test = WebSocketModuleTest()
test.setup_test_connections()
# 模拟实际使用场景
logger.info("模拟实际使用场景...")
# 场景1广播消息给所有客户端
all_ips = test.module.get_websocket_client_ip()
for ip in all_ips:
try:
test.module.send_msg_to_wsc_by_client_ip(f"广播消息给 {ip}", ip)
await asyncio.sleep(0.05)
except Exception as e:
logger.error(f"发送广播消息失败: {e}")
# 场景2向特定任务发送状态更新
test.module.send_msg_to_wsc_by_client_name("任务状态: 执行中", "task_001")
await asyncio.sleep(0.05)
# 场景3获取连接统计信息
client_count = len(test.module.get_websocket_client_name())
logger.info(f"当前连接客户端数量: {client_count}")
logger.info("✓ WebSocket集成测试完成")
asyncio.run(integration_test())
if __name__ == "__main__":
logger.info("开始WebSocket模块完整测试")
try:
# 运行基本功能测试
run_mock_websocket_server()
# 运行集成测试
test_websocket_integration()
logger.info("✅ 所有WebSocket模块测试成功完成")
except Exception as e:
logger.error(f"❌ WebSocket模块测试失败: {e}")
raise