Skip to main content
Glama
Huangwh826

Halo MCP Server

by Huangwh826
run_comprehensive_test.py28.6 kB
"""Halo MCP Server 综合测试套件 覆盖所有 30 个 MCP 工具的完整测试,包括: - 分类管理 (6个工具) - 标签管理 (7个工具) - 附件管理 (8个工具) - 文章管理 (9个工具) 可直接运行,无需额外依赖。 使用方法: python run_comprehensive_test.py 环境要求: - Python 3.10+ - 配置 HALO_BASE_URL 和 HALO_TOKEN 环境变量 """ import asyncio import json import os import sys import tempfile from datetime import datetime from pathlib import Path # 添加项目根目录到路径 project_root = Path(__file__).parent.parent sys.path.insert(0, str(project_root / "src")) from loguru import logger from halo_mcp_server.client.halo_client import HaloClient class HaloMCPComprehensiveTest: """Halo MCP Server 全面测试类""" def __init__(self): self.client = None self.test_data = { "category_names": [], "tag_names": [], "attachment_names": [], "post_names": [], "group_names": [], } self.test_results = [] async def setup(self): """初始化测试环境""" logger.info("=" * 80) logger.info("🚀 开始 Halo MCP Server 全面测试") logger.info("=" * 80) self.client = HaloClient() await self.client.connect() await self.client.authenticate() logger.success("✓ 客户端初始化成功") async def teardown(self): """清理测试环境""" if self.client: await self.client.close() logger.info("=" * 80) logger.success("✓ 测试环境清理完成") def log_test(self, test_num, test_name, description): """记录测试信息""" logger.info("=" * 80) logger.info(f"测试 {test_num}/30: {test_name}") logger.info(f"描述: {description}") logger.info("=" * 80) def record_result(self, test_num, test_name, success, message=""): """记录测试结果""" result = { "test_num": test_num, "test_name": test_name, "success": success, "message": message, "timestamp": datetime.now().isoformat(), } self.test_results.append(result) if success: logger.success(f"✓ 测试 {test_num} 通过: {test_name}") else: logger.error(f"✗ 测试 {test_num} 失败: {test_name} - {message}") # ==================== 分类管理工具 (6个) ==================== async def test_01_create_category(self): """测试 1: 创建分类""" from halo_mcp_server.tools.category_tools import create_category_tool self.log_test(1, "create_category", "创建博客分类") try: assert self.client is not None args = { "display_name": f"自动化测试分类_{datetime.now().strftime('%H%M%S')}", "slug": f"test-category-{datetime.now().strftime('%Y%m%d%H%M%S')}", "description": "自动化测试创建的分类", "priority": 10, } result = await create_category_tool(self.client, args) result_data = json.loads(result) if result_data.get("success"): self.test_data["category_names"].append(result_data["data"]["category_name"]) self.record_result(1, "create_category", True, f"分类: {result_data['data']['display_name']}") else: self.record_result(1, "create_category", False, result_data.get("message")) except Exception as e: self.record_result(1, "create_category", False, str(e)) async def test_02_list_categories(self): """测试 2: 列出分类""" from halo_mcp_server.tools.category_tools import list_categories_tool self.log_test(2, "list_categories", "列出所有分类") try: assert self.client is not None args = {"page": 0, "size": 50} result = await list_categories_tool(self.client, args) result_data = json.loads(result) count = len(result_data.get("items", [])) self.record_result(2, "list_categories", True, f"找到 {count} 个分类") except Exception as e: self.record_result(2, "list_categories", False, str(e)) async def test_03_get_category(self): """测试 3: 获取分类详情""" from halo_mcp_server.tools.category_tools import get_category_tool self.log_test(3, "get_category", "获取分类详细信息") try: assert self.client is not None if not self.test_data["category_names"]: self.record_result(3, "get_category", False, "没有可用的分类") return args = {"name": self.test_data["category_names"][0]} result = await get_category_tool(self.client, args) result_data = json.loads(result) self.record_result(3, "get_category", True, f"分类: {result_data['spec']['displayName']}") except Exception as e: self.record_result(3, "get_category", False, str(e)) async def test_04_update_category(self): """测试 4: 更新分类""" from halo_mcp_server.tools.category_tools import update_category_tool self.log_test(4, "update_category", "更新分类信息") try: assert self.client is not None if not self.test_data["category_names"]: self.record_result(4, "update_category", False, "没有可用的分类") return args = { "name": self.test_data["category_names"][0], "description": "更新后的描述", "priority": 20, } result = await update_category_tool(self.client, args) result_data = json.loads(result) self.record_result(4, "update_category", result_data.get("success", False)) except Exception as e: self.record_result(4, "update_category", False, str(e)) async def test_05_get_category_posts(self): """测试 5: 获取分类下的文章""" from halo_mcp_server.tools.category_tools import get_posts_under_category_tool self.log_test(5, "get_category_posts", "获取分类下的文章列表") try: assert self.client is not None if not self.test_data["category_names"]: self.record_result(5, "get_category_posts", False, "没有可用的分类") return args = {"name": self.test_data["category_names"][0], "page": 0, "size": 20} result = await get_posts_under_category_tool(self.client, args) self.record_result(5, "get_category_posts", True) except Exception as e: self.record_result(5, "get_category_posts", False, str(e)) # ==================== 标签管理工具 (7个) ==================== async def test_06_create_tag(self): """测试 6: 创建标签""" from halo_mcp_server.tools.tag_tools import create_tag_tool self.log_test(6, "create_tag", "创建博客标签") try: for i in range(2): args = { "display_name": f"测试标签{i+1}_{datetime.now().strftime('%H%M%S')}", "color": "#FF5733" if i == 0 else "#33FF57", } result = await create_tag_tool(self.client, args) result_data = json.loads(result) if result_data.get("success"): self.test_data["tag_names"].append(result_data["data"]["tag_name"]) self.record_result(6, "create_tag", True, f"创建了 {len(self.test_data['tag_names'])} 个标签") except Exception as e: self.record_result(6, "create_tag", False, str(e)) async def test_07_list_tags(self): """测试 7: 列出标签""" from halo_mcp_server.tools.tag_tools import list_tags_tool self.log_test(7, "list_tags", "列出所有标签") try: args = {"page": 0, "size": 100} result = await list_tags_tool(self.client, args) result_data = json.loads(result) count = len(result_data.get("items", [])) self.record_result(7, "list_tags", True, f"找到 {count} 个标签") except Exception as e: self.record_result(7, "list_tags", False, str(e)) async def test_08_get_tag(self): """测试 8: 获取标签详情""" from halo_mcp_server.tools.tag_tools import get_tag_tool self.log_test(8, "get_tag", "获取标签详细信息") try: if not self.test_data["tag_names"]: self.record_result(8, "get_tag", False, "没有可用的标签") return args = {"name": self.test_data["tag_names"][0]} result = await get_tag_tool(self.client, args) result_data = json.loads(result) self.record_result(8, "get_tag", True, f"标签: {result_data['spec']['displayName']}") except Exception as e: self.record_result(8, "get_tag", False, str(e)) async def test_09_update_tag(self): """测试 9: 更新标签""" from halo_mcp_server.tools.tag_tools import update_tag_tool self.log_test(9, "update_tag", "更新标签信息") try: if not self.test_data["tag_names"]: self.record_result(9, "update_tag", False, "没有可用的标签") return args = {"name": self.test_data["tag_names"][0], "color": "#FFA500"} result = await update_tag_tool(self.client, args) result_data = json.loads(result) self.record_result(9, "update_tag", result_data.get("success", False)) except Exception as e: self.record_result(9, "update_tag", False, str(e)) async def test_10_list_console_tags(self): """测试 10: 列出控制台标签""" from halo_mcp_server.tools.tag_tools import list_console_tags_tool self.log_test(10, "list_console_tags", "列出控制台标签") try: args = {"page": 0, "size": 100} result = await list_console_tags_tool(self.client, args) result_data = json.loads(result) count = len(result_data.get("items", [])) self.record_result(10, "list_console_tags", True, f"找到 {count} 个控制台标签") except Exception as e: self.record_result(10, "list_console_tags", False, str(e)) async def test_11_get_tag_posts(self): """测试 11: 获取标签下的文章""" from halo_mcp_server.tools.tag_tools import get_posts_under_tag_tool self.log_test(11, "get_tag_posts", "获取标签下的文章列表") try: if not self.test_data["tag_names"]: self.record_result(11, "get_tag_posts", False, "没有可用的标签") return args = {"name": self.test_data["tag_names"][0], "page": 0, "size": 20} result = await get_posts_under_tag_tool(self.client, args) self.record_result(11, "get_tag_posts", True) except Exception as e: self.record_result(11, "get_tag_posts", False, str(e)) # ==================== 附件管理工具 (8个) ==================== async def test_12_list_attachment_groups(self): """测试 12: 列出附件分组""" from halo_mcp_server.tools.attachment_tools import list_attachment_groups_tool self.log_test(12, "list_attachment_groups", "列出附件分组") try: args = {"page": 0, "size": 100} result = await list_attachment_groups_tool(self.client, args) self.record_result(12, "list_attachment_groups", True) except Exception as e: self.record_result(12, "list_attachment_groups", False, str(e)) async def test_13_create_attachment_group(self): """测试 13: 创建附件分组""" from halo_mcp_server.tools.attachment_tools import create_attachment_group_tool self.log_test(13, "create_attachment_group", "创建附件分组") try: args = {"display_name": f"测试附件分组_{datetime.now().strftime('%H%M%S')}"} result = await create_attachment_group_tool(self.client, args) result_data = json.loads(result) if result_data.get("success"): self.test_data["group_names"].append(result_data["data"]["group_name"]) self.record_result(13, "create_attachment_group", True) else: self.record_result(13, "create_attachment_group", False, result_data.get("message")) except Exception as e: self.record_result(13, "create_attachment_group", False, str(e)) async def test_14_get_attachment_policies(self): """测试 14: 获取存储策略""" from halo_mcp_server.tools.attachment_tools import list_storage_policies_tool self.log_test(14, "get_attachment_policies", "获取存储策略列表") try: args = {"random_string": "test"} result = await list_storage_policies_tool(self.client, args) self.record_result(14, "get_attachment_policies", True) except Exception as e: self.record_result(14, "get_attachment_policies", False, str(e)) async def test_15_upload_attachment(self): """测试 15: 上传本地文件""" from halo_mcp_server.tools.attachment_tools import upload_attachment_tool self.log_test(15, "upload_attachment", "上传本地文件作为附件") try: # 创建临时文件 with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f: f.write(f"测试文件\n创建时间: {datetime.now().isoformat()}\n") temp_file_path = f.name try: args = {"file_path": temp_file_path, "policy_name": "default-policy"} result = await upload_attachment_tool(self.client, args) result_data = json.loads(result) if result_data.get("success"): self.test_data["attachment_names"].append(result_data["data"]["attachment_name"]) self.record_result(15, "upload_attachment", True) else: self.record_result(15, "upload_attachment", False, result_data.get("message")) finally: if os.path.exists(temp_file_path): os.unlink(temp_file_path) except Exception as e: self.record_result(15, "upload_attachment", False, str(e)) async def test_16_list_attachments(self): """测试 16: 列出附件""" from halo_mcp_server.tools.attachment_tools import list_attachments_tool self.log_test(16, "list_attachments", "列出所有附件") try: args = {"page": 0, "size": 50} result = await list_attachments_tool(self.client, args) self.record_result(16, "list_attachments", True) except Exception as e: self.record_result(16, "list_attachments", False, str(e)) async def test_17_get_attachment(self): """测试 17: 获取附件详情""" from halo_mcp_server.tools.attachment_tools import get_attachment_tool self.log_test(17, "get_attachment", "获取附件详细信息") try: if not self.test_data["attachment_names"]: self.record_result(17, "get_attachment", True, "跳过(无附件)") return args = {"name": self.test_data["attachment_names"][0]} result = await get_attachment_tool(self.client, args) self.record_result(17, "get_attachment", True) except Exception as e: self.record_result(17, "get_attachment", False, str(e)) # ==================== 文章管理工具 (9个) ==================== async def test_18_create_post(self): """测试 18: 创建文章""" from halo_mcp_server.tools.post_tools import create_post_tool self.log_test(18, "create_post", "创建博客文章") try: content = f"""# 自动化测试文章 这是自动化测试创建的文章。 ## 测试信息 - 创建时间: {datetime.now().isoformat()} - 测试工具: Halo MCP Server ## 内容 这是测试内容。 """ args = { "title": f"自动化测试文章_{datetime.now().strftime('%Y%m%d_%H%M%S')}", "content": content, "excerpt": "自动化测试文章", "categories": self.test_data["category_names"][:1], "tags": self.test_data["tag_names"][:2], } result = await create_post_tool(self.client, args) result_data = json.loads(result) if result_data.get("success"): self.test_data["post_names"].append(result_data["data"]["post_name"]) self.record_result(18, "create_post", True, f"文章: {args['title']}") else: self.record_result(18, "create_post", False, result_data.get("message")) except Exception as e: self.record_result(18, "create_post", False, str(e)) async def test_19_list_my_posts(self): """测试 19: 列出文章""" from halo_mcp_server.tools.post_tools import list_my_posts_tool self.log_test(19, "list_my_posts", "列出用户的所有文章") try: args = {"page": 0, "size": 20} result = await list_my_posts_tool(self.client, args) result_data = json.loads(result) count = len(result_data.get("items", [])) self.record_result(19, "list_my_posts", True, f"找到 {count} 篇文章") except Exception as e: self.record_result(19, "list_my_posts", False, str(e)) async def test_20_get_post(self): """测试 20: 获取文章详情""" from halo_mcp_server.tools.post_tools import get_post_tool self.log_test(20, "get_post", "获取文章详细信息") try: if not self.test_data["post_names"]: self.record_result(20, "get_post", False, "没有可用的文章") return args = {"name": self.test_data["post_names"][0]} result = await get_post_tool(self.client, args) result_data = json.loads(result) self.record_result(20, "get_post", True, f"文章: {result_data['spec']['title']}") except Exception as e: self.record_result(20, "get_post", False, str(e)) async def test_21_get_post_draft(self): """测试 21: 获取文章草稿""" from halo_mcp_server.tools.post_tools import get_post_draft_tool self.log_test(21, "get_post_draft", "获取文章草稿") try: if not self.test_data["post_names"]: self.record_result(21, "get_post_draft", False, "没有可用的文章") return args = {"name": self.test_data["post_names"][0]} result = await get_post_draft_tool(self.client, args) self.record_result(21, "get_post_draft", True) except Exception as e: self.record_result(21, "get_post_draft", False, str(e)) async def test_22_update_post_draft(self): """测试 22: 更新文章草稿""" from halo_mcp_server.tools.post_tools import update_post_draft_tool self.log_test(22, "update_post_draft", "更新文章草稿内容") try: if not self.test_data["post_names"]: self.record_result(22, "update_post_draft", False, "没有可用的文章") return updated_content = f"# 更新后的测试文章\n\n更新时间: {datetime.now().isoformat()}\n" args = {"name": self.test_data["post_names"][0], "content": updated_content} result = await update_post_draft_tool(self.client, args) result_data = json.loads(result) self.record_result(22, "update_post_draft", result_data.get("success", False)) except Exception as e: self.record_result(22, "update_post_draft", False, str(e)) async def test_23_update_post(self): """测试 23: 更新文章""" from halo_mcp_server.tools.post_tools import update_post_tool self.log_test(23, "update_post", "更新文章元数据") try: if not self.test_data["post_names"]: self.record_result(23, "update_post", False, "没有可用的文章") return args = { "name": self.test_data["post_names"][0], "excerpt": f"更新后的摘要 - {datetime.now().isoformat()}", } result = await update_post_tool(self.client, args) result_data = json.loads(result) self.record_result(23, "update_post", result_data.get("success", False)) except Exception as e: self.record_result(23, "update_post", False, str(e)) async def test_24_publish_post(self): """测试 24: 发布文章""" from halo_mcp_server.tools.post_tools import publish_post_tool self.log_test(24, "publish_post", "发布文章") try: if not self.test_data["post_names"]: self.record_result(24, "publish_post", False, "没有可用的文章") return args = {"name": self.test_data["post_names"][0]} result = await publish_post_tool(self.client, args) result_data = json.loads(result) self.record_result(24, "publish_post", result_data.get("success", False)) except Exception as e: self.record_result(24, "publish_post", False, str(e)) async def test_25_unpublish_post(self): """测试 25: 取消发布文章""" from halo_mcp_server.tools.post_tools import unpublish_post_tool self.log_test(25, "unpublish_post", "取消发布文章") try: if not self.test_data["post_names"]: self.record_result(25, "unpublish_post", False, "没有可用的文章") return args = {"name": self.test_data["post_names"][0]} result = await unpublish_post_tool(self.client, args) result_data = json.loads(result) self.record_result(25, "unpublish_post", result_data.get("success", False)) except Exception as e: self.record_result(25, "unpublish_post", False, str(e)) # ==================== 清理测试数据 ==================== async def test_26_delete_post(self): """测试 26: 删除文章""" from halo_mcp_server.tools.post_tools import delete_post_tool self.log_test(26, "delete_post", "删除文章") try: for post_name in self.test_data["post_names"]: args = {"name": post_name} await delete_post_tool(self.client, args) self.record_result(26, "delete_post", True, f"删除了 {len(self.test_data['post_names'])} 篇文章") except Exception as e: self.record_result(26, "delete_post", False, str(e)) async def test_27_delete_attachment(self): """测试 27: 删除附件""" from halo_mcp_server.tools.attachment_tools import delete_attachment_tool self.log_test(27, "delete_attachment", "删除附件") try: for attachment_name in self.test_data["attachment_names"]: args = {"name": attachment_name} try: await delete_attachment_tool(self.client, args) except: pass self.record_result(27, "delete_attachment", True) except Exception as e: self.record_result(27, "delete_attachment", False, str(e)) async def test_28_delete_tag(self): """测试 28: 删除标签""" from halo_mcp_server.tools.tag_tools import delete_tag_tool self.log_test(28, "delete_tag", "删除标签") try: for tag_name in self.test_data["tag_names"]: args = {"name": tag_name} await delete_tag_tool(self.client, args) self.record_result(28, "delete_tag", True, f"删除了 {len(self.test_data['tag_names'])} 个标签") except Exception as e: self.record_result(28, "delete_tag", False, str(e)) async def test_29_delete_category(self): """测试 29: 删除分类""" from halo_mcp_server.tools.category_tools import delete_category_tool self.log_test(29, "delete_category", "删除分类") try: for category_name in self.test_data["category_names"]: args = {"name": category_name} await delete_category_tool(self.client, args) self.record_result(29, "delete_category", True, f"删除了 {len(self.test_data['category_names'])} 个分类") except Exception as e: self.record_result(29, "delete_category", False, str(e)) # ==================== 运行所有测试 ==================== async def run_all_tests(self): """运行所有测试""" await self.setup() try: # 按顺序运行所有测试 await self.test_01_create_category() await self.test_02_list_categories() await self.test_03_get_category() await self.test_04_update_category() await self.test_05_get_category_posts() await self.test_06_create_tag() await self.test_07_list_tags() await self.test_08_get_tag() await self.test_09_update_tag() await self.test_10_list_console_tags() await self.test_11_get_tag_posts() await self.test_12_list_attachment_groups() await self.test_13_create_attachment_group() await self.test_14_get_attachment_policies() await self.test_15_upload_attachment() await self.test_16_list_attachments() await self.test_17_get_attachment() await self.test_18_create_post() await self.test_19_list_my_posts() await self.test_20_get_post() await self.test_21_get_post_draft() await self.test_22_update_post_draft() await self.test_23_update_post() await self.test_24_publish_post() await self.test_25_unpublish_post() # 清理 await self.test_26_delete_post() await self.test_27_delete_attachment() await self.test_28_delete_tag() await self.test_29_delete_category() finally: await self.teardown() # 输出测试总结 self.print_summary() def print_summary(self): """打印测试总结""" logger.info("=" * 80) logger.info("🎉 测试总结") logger.info("=" * 80) total = len(self.test_results) passed = sum(1 for r in self.test_results if r["success"]) failed = total - passed logger.info(f"\n总测试数: {total}") logger.success(f"✓ 通过: {passed}") if failed > 0: logger.error(f"✗ 失败: {failed}") logger.info(f"\n创建的资源:") logger.info(f" - 分类: {len(self.test_data['category_names'])}") logger.info(f" - 标签: {len(self.test_data['tag_names'])}") logger.info(f" - 附件: {len(self.test_data['attachment_names'])}") logger.info(f" - 文章: {len(self.test_data['post_names'])}") logger.info(f" - 分组: {len(self.test_data['group_names'])}") if failed > 0: logger.info(f"\n失败的测试:") for result in self.test_results: if not result["success"]: logger.error( f" ✗ 测试 {result['test_num']}: {result['test_name']} - {result['message']}" ) logger.info("=" * 80) async def main(): """主函数""" test = HaloMCPComprehensiveTest() await test.run_all_tests() if __name__ == "__main__": asyncio.run(main())

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Huangwh826/halo-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server