""" WebSocket实时通信测试用例 """ import pytest import asyncio import json import os from websockets.client import connect from websockets.exceptions import ConnectionClosed @pytest.mark.websocket @pytest.mark.regression class TestWebSocket: """WebSocket实时通信测试类""" @pytest.fixture def websocket_url(self): """WebSocket连接URL""" api_base_url = os.getenv("API_BASE_URL", "http://localhost:8084") ws_url = api_base_url.replace("http://", "ws://") return f"{ws_url}/ws" @pytest.fixture async def websocket_connection(self, websocket_url): """WebSocket连接fixture""" async with connect(websocket_url) as websocket: yield websocket @pytest.fixture async def authenticated_websocket(self, websocket_url, authenticated_client): """带认证的WebSocket连接""" token = authenticated_client.headers.get("Authorization") url_with_token = f"{websocket_url}?token={token.replace('Bearer ', '')}" async with connect(url_with_token) as websocket: yield websocket @pytest.mark.asyncio async def test_websocket_connection(self, websocket_url): """测试WebSocket连接建立""" try: async with connect(websocket_url) as websocket: assert websocket.open except ConnectionRefusedError: pytest.skip("WebSocket服务未启动") @pytest.mark.asyncio async def test_websocket_ping_pong(self, websocket_connection): """测试WebSocket心跳机制""" ping_message = { "type": "ping", "timestamp": 1234567890 } await websocket_connection.send(json.dumps(ping_message)) response = await asyncio.wait_for(websocket_connection.recv(), timeout=5.0) pong_message = json.loads(response) assert pong_message["type"] == "pong" assert "timestamp" in pong_message @pytest.mark.asyncio async def test_websocket_subscribe(self, websocket_connection): """测试WebSocket订阅""" subscribe_message = { "type": "subscribe", "channel": "notifications" } await websocket_connection.send(json.dumps(subscribe_message)) response = await asyncio.wait_for(websocket_connection.recv(), timeout=5.0) message = json.loads(response) assert message["type"] in ["subscribe_ack", "pong"] @pytest.mark.asyncio async def test_websocket_multiple_messages(self, websocket_connection): """测试WebSocket多消息处理""" messages = [ {"type": "ping"}, {"type": "subscribe", "channel": "test"}, {"type": "ping"} ] responses = [] for msg in messages: await websocket_connection.send(json.dumps(msg)) try: response = await asyncio.wait_for(websocket_connection.recv(), timeout=2.0) responses.append(json.loads(response)) except asyncio.TimeoutError: pass assert len(responses) >= 2 @pytest.mark.asyncio async def test_websocket_invalid_message(self, websocket_connection): """测试WebSocket无效消息处理""" invalid_messages = [ "invalid json", "", json.dumps({"type": "unknown_type"}), json.dumps({}) ] for msg in invalid_messages: try: await websocket_connection.send(msg) await asyncio.sleep(0.5) except Exception: pass @pytest.mark.asyncio async def test_websocket_connection_close(self, websocket_url): """测试WebSocket连接关闭""" async with connect(websocket_url) as websocket: assert websocket.open await websocket.close() assert not websocket.open @pytest.mark.asyncio async def test_websocket_timeout(self, websocket_url): """测试WebSocket超时""" try: async with connect(websocket_url, ping_timeout=2.0) as websocket: await asyncio.sleep(3.0) except (ConnectionClosed, asyncio.TimeoutError): pass @pytest.mark.asyncio async def test_websocket_concurrent_connections(self, websocket_url): """测试WebSocket并发连接""" async def create_connection(): try: async with connect(websocket_url) as websocket: await websocket.send(json.dumps({"type": "ping"})) await asyncio.wait_for(websocket_connection.recv(), timeout=2.0) except Exception: pass connections = [create_connection() for _ in range(5)] await asyncio.gather(*connections, return_exceptions=True) @pytest.mark.asyncio async def test_websocket_large_message(self, websocket_connection): """测试WebSocket大消息处理""" large_data = "x" * 10000 message = { "type": "test", "data": large_data } await websocket_connection.send(json.dumps(message)) try: response = await asyncio.wait_for(websocket_connection.recv(), timeout=5.0) assert response except asyncio.TimeoutError: pass @pytest.mark.asyncio async def test_websocket_reconnect(self, websocket_url): """测试WebSocket重连""" for i in range(3): try: async with connect(websocket_url) as websocket: await websocket.send(json.dumps({"type": "ping"})) response = await asyncio.wait_for(websocket.recv(), timeout=2.0) assert response except Exception: pass @pytest.mark.asyncio async def test_websocket_unicode_message(self, websocket_connection): """测试WebSocket Unicode消息""" unicode_message = { "type": "test", "content": "测试中文🎉🚀" } await websocket_connection.send(json.dumps(unicode_message)) try: response = await asyncio.wait_for(websocket_connection.recv(), timeout=2.0) assert response except asyncio.TimeoutError: pass