mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 02:22:26 +08:00
🐛 修復單元測試問題
This commit is contained in:
parent
85ff83f037
commit
5150617abb
@ -83,25 +83,37 @@ class I18nManager:
|
||||
if env_lang and env_lang in self._supported_languages:
|
||||
return env_lang
|
||||
|
||||
# 3. 自動偵測系統語言
|
||||
try:
|
||||
# 獲取系統語言
|
||||
system_locale = locale.getdefaultlocale()[0]
|
||||
if system_locale:
|
||||
if system_locale.startswith("zh_TW") or system_locale.startswith(
|
||||
"zh_Hant"
|
||||
):
|
||||
# 3. 檢查其他環境變數(LANG, LC_ALL 等)
|
||||
for env_var in ["LANG", "LC_ALL", "LC_MESSAGES", "LANGUAGE"]:
|
||||
env_value = os.getenv(env_var, "").strip()
|
||||
if env_value:
|
||||
if env_value.startswith("zh_TW") or env_value.startswith("zh_Hant"):
|
||||
return "zh-TW"
|
||||
if system_locale.startswith("zh_CN") or system_locale.startswith(
|
||||
"zh_Hans"
|
||||
):
|
||||
if env_value.startswith("zh_CN") or env_value.startswith("zh_Hans"):
|
||||
return "zh-CN"
|
||||
if system_locale.startswith("en"):
|
||||
if env_value.startswith("en"):
|
||||
return "en"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 4. 回退到默認語言
|
||||
# 4. 自動偵測系統語言(僅在非測試模式下)
|
||||
if not os.getenv("MCP_TEST_MODE"):
|
||||
try:
|
||||
# 獲取系統語言
|
||||
system_locale = locale.getdefaultlocale()[0]
|
||||
if system_locale:
|
||||
if system_locale.startswith("zh_TW") or system_locale.startswith(
|
||||
"zh_Hant"
|
||||
):
|
||||
return "zh-TW"
|
||||
if system_locale.startswith("zh_CN") or system_locale.startswith(
|
||||
"zh_Hans"
|
||||
):
|
||||
return "zh-CN"
|
||||
if system_locale.startswith("en"):
|
||||
return "en"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 5. 回退到默認語言
|
||||
return self._fallback_language
|
||||
|
||||
def _load_saved_language(self) -> str | None:
|
||||
|
@ -47,12 +47,16 @@ class WebUIManager:
|
||||
if env_port:
|
||||
try:
|
||||
custom_port = int(env_port)
|
||||
if 1024 <= custom_port <= 65535:
|
||||
if custom_port == 0:
|
||||
# 特殊值 0 表示使用系統自動分配的端口
|
||||
preferred_port = 0
|
||||
debug_log("使用環境變數指定的自動端口分配 (0)")
|
||||
elif 1024 <= custom_port <= 65535:
|
||||
preferred_port = custom_port
|
||||
debug_log(f"使用環境變數指定的端口: {preferred_port}")
|
||||
else:
|
||||
debug_log(
|
||||
f"MCP_WEB_PORT 值無效 ({custom_port}),必須在 1024-65535 範圍內,使用預設端口 8765"
|
||||
f"MCP_WEB_PORT 值無效 ({custom_port}),必須在 1024-65535 範圍內或為 0,使用預設端口 8765"
|
||||
)
|
||||
except ValueError:
|
||||
debug_log(
|
||||
@ -63,9 +67,23 @@ class WebUIManager:
|
||||
|
||||
# 使用增強的端口管理,測試模式下禁用自動清理避免權限問題
|
||||
auto_cleanup = os.environ.get("MCP_TEST_MODE", "").lower() != "true"
|
||||
self.port = port or PortManager.find_free_port_enhanced(
|
||||
preferred_port=preferred_port, auto_cleanup=auto_cleanup, host=self.host
|
||||
)
|
||||
|
||||
if port is not None:
|
||||
# 如果明確指定了端口,使用指定的端口
|
||||
self.port = port
|
||||
elif preferred_port == 0:
|
||||
# 如果偏好端口為 0,使用系統自動分配
|
||||
import socket
|
||||
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||
s.bind((self.host, 0))
|
||||
self.port = s.getsockname()[1]
|
||||
debug_log(f"系統自動分配端口: {self.port}")
|
||||
else:
|
||||
# 使用增強的端口管理
|
||||
self.port = PortManager.find_free_port_enhanced(
|
||||
preferred_port=preferred_port, auto_cleanup=auto_cleanup, host=self.host
|
||||
)
|
||||
self.app = FastAPI(title="MCP Feedback Enhanced")
|
||||
|
||||
# 設置壓縮和緩存中間件
|
||||
|
@ -50,13 +50,35 @@ def test_project_dir(temp_dir: Path) -> Path:
|
||||
@pytest.fixture
|
||||
def web_ui_manager() -> Generator[WebUIManager, None, None]:
|
||||
"""創建 WebUIManager fixture"""
|
||||
manager = WebUIManager(host="127.0.0.1", port=0) # 使用隨機端口
|
||||
yield manager
|
||||
import os
|
||||
|
||||
# 清理
|
||||
if manager.server_thread and manager.server_thread.is_alive():
|
||||
# 這裡可以添加服務器停止邏輯
|
||||
pass
|
||||
# 設置測試模式環境變數
|
||||
original_test_mode = os.environ.get("MCP_TEST_MODE")
|
||||
original_web_port = os.environ.get("MCP_WEB_PORT")
|
||||
|
||||
os.environ["MCP_TEST_MODE"] = "true"
|
||||
# 使用動態端口範圍避免衝突
|
||||
os.environ["MCP_WEB_PORT"] = "0" # 讓系統自動分配端口
|
||||
|
||||
try:
|
||||
manager = WebUIManager(host="127.0.0.1") # 使用環境變數控制端口
|
||||
yield manager
|
||||
finally:
|
||||
# 恢復原始環境變數
|
||||
if original_test_mode is not None:
|
||||
os.environ["MCP_TEST_MODE"] = original_test_mode
|
||||
else:
|
||||
os.environ.pop("MCP_TEST_MODE", None)
|
||||
|
||||
if original_web_port is not None:
|
||||
os.environ["MCP_WEB_PORT"] = original_web_port
|
||||
else:
|
||||
os.environ.pop("MCP_WEB_PORT", None)
|
||||
|
||||
# 清理
|
||||
if manager.server_thread and manager.server_thread.is_alive():
|
||||
# 這裡可以添加服務器停止邏輯
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -26,8 +26,8 @@ class SimpleMCPClient:
|
||||
async def start_server(self) -> bool:
|
||||
"""啟動 MCP 服務器"""
|
||||
try:
|
||||
# 使用當前專案的 MCP 服務器
|
||||
cmd = ["python", "-m", "mcp_feedback_enhanced.server"]
|
||||
# 使用正確的 uv run 命令啟動 MCP 服務器
|
||||
cmd = ["uv", "run", "python", "-m", "mcp_feedback_enhanced"]
|
||||
|
||||
self.server_process = subprocess.Popen(
|
||||
cmd,
|
||||
@ -37,6 +37,8 @@ class SimpleMCPClient:
|
||||
text=True,
|
||||
bufsize=0,
|
||||
cwd=Path.cwd(),
|
||||
encoding="utf-8", # 明確指定 UTF-8 編碼
|
||||
errors="replace", # 處理編碼錯誤
|
||||
)
|
||||
|
||||
self.stdin = self.server_process.stdin
|
||||
|
@ -106,9 +106,10 @@ class TestI18NFileSystemIntegration:
|
||||
|
||||
assert locales_dir.exists(), f"翻譯目錄不存在: {locales_dir}"
|
||||
|
||||
# 檢查每種支援語言的翻譯文件
|
||||
# 檢查每種支援語言的翻譯文件(使用正確的路徑結構)
|
||||
for lang in TestData.SUPPORTED_LANGUAGES:
|
||||
lang_file = locales_dir / f"{lang}.json"
|
||||
lang_dir = locales_dir / lang
|
||||
lang_file = lang_dir / "translation.json"
|
||||
assert lang_file.exists(), f"翻譯文件不存在: {lang_file}"
|
||||
|
||||
# 檢查文件內容
|
||||
@ -132,7 +133,8 @@ class TestI18NFileSystemIntegration:
|
||||
locales_dir = manager._locales_dir
|
||||
|
||||
for lang in TestData.SUPPORTED_LANGUAGES:
|
||||
lang_file = locales_dir / f"{lang}.json"
|
||||
lang_dir = locales_dir / lang
|
||||
lang_file = lang_dir / "translation.json"
|
||||
|
||||
if lang_file.exists():
|
||||
# 測試 UTF-8 編碼
|
||||
@ -160,6 +162,9 @@ class TestI18NEnvironmentIntegration:
|
||||
try:
|
||||
# 測試不同的環境設置
|
||||
test_cases = [
|
||||
{"MCP_LANGUAGE": "zh-TW", "expected": "zh-TW"},
|
||||
{"MCP_LANGUAGE": "zh-CN", "expected": "zh-CN"},
|
||||
{"MCP_LANGUAGE": "en", "expected": "en"},
|
||||
{"LANG": "zh_TW.UTF-8", "expected": "zh-TW"},
|
||||
{"LANG": "zh_CN.UTF-8", "expected": "zh-CN"},
|
||||
{"LANG": "en_US.UTF-8", "expected": "en"},
|
||||
@ -170,22 +175,34 @@ class TestI18NEnvironmentIntegration:
|
||||
# 清理環境變數
|
||||
for var in env_vars:
|
||||
os.environ.pop(var, None)
|
||||
# 也清理 MCP_LANGUAGE
|
||||
os.environ.pop("MCP_LANGUAGE", None)
|
||||
|
||||
# 設置測試模式,禁用系統語言檢測
|
||||
os.environ["MCP_TEST_MODE"] = "true"
|
||||
|
||||
# 設置測試環境
|
||||
for key, value in test_case.items():
|
||||
if key != "expected":
|
||||
os.environ[key] = value
|
||||
|
||||
# 創建新的管理器實例
|
||||
manager = I18nManager()
|
||||
# 修復 attr-defined 錯誤 - 使用正確的方法名
|
||||
detected = manager._detect_language()
|
||||
# 創建新的管理器實例,並清理可能的保存設定
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
# 驗證檢測結果
|
||||
expected = test_case["expected"]
|
||||
assert detected == expected, (
|
||||
f"環境 {test_case} 檢測到 {detected},預期 {expected}"
|
||||
)
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# 臨時修改配置文件路徑,避免使用真實的用戶配置
|
||||
manager = I18nManager()
|
||||
manager._config_file = Path(temp_dir) / "test_language.json"
|
||||
|
||||
# 修復 attr-defined 錯誤 - 使用正確的方法名
|
||||
detected = manager._detect_language()
|
||||
|
||||
# 驗證檢測結果
|
||||
expected = test_case["expected"]
|
||||
assert detected == expected, (
|
||||
f"環境 {test_case} 檢測到 {detected},預期 {expected}"
|
||||
)
|
||||
|
||||
finally:
|
||||
# 恢復原始環境變數
|
||||
|
@ -97,6 +97,24 @@ class TestWebUIIntegration:
|
||||
data = msg.json()
|
||||
assert data["type"] == "connection_established"
|
||||
|
||||
# 可能會收到額外的消息(session_updated 或 status_update),先處理掉
|
||||
try:
|
||||
while True:
|
||||
extra_msg = await asyncio.wait_for(ws.receive(), timeout=1)
|
||||
if extra_msg.type == aiohttp.WSMsgType.TEXT:
|
||||
extra_data = extra_msg.json()
|
||||
if extra_data["type"] in [
|
||||
"session_updated",
|
||||
"status_update",
|
||||
]:
|
||||
continue
|
||||
# 如果是其他類型的消息,可能是我們要的回應,先保存
|
||||
break
|
||||
break
|
||||
except TimeoutError:
|
||||
# 沒有額外消息,繼續測試
|
||||
pass
|
||||
|
||||
# 測試發送心跳
|
||||
heartbeat_msg = {
|
||||
"type": "heartbeat",
|
||||
|
@ -33,6 +33,11 @@ class TestResourceManager:
|
||||
# 重置單例實例
|
||||
ResourceManager._instance = None
|
||||
|
||||
# 重置全局資源管理器實例
|
||||
import mcp_feedback_enhanced.utils.resource_manager as rm_module
|
||||
|
||||
rm_module._resource_manager = None
|
||||
|
||||
def test_singleton_pattern(self):
|
||||
"""測試單例模式"""
|
||||
rm1 = ResourceManager()
|
||||
|
Loading…
x
Reference in New Issue
Block a user