test_table_inspector_api.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. #!/usr/bin/env python3
  2. """
  3. 表检查API测试脚本
  4. 用于测试新实现的表列表获取API功能
  5. """
  6. import requests
  7. import json
  8. # 测试配置
  9. API_BASE_URL = "http://localhost:8084"
  10. ENDPOINT = "/api/v0/database/tables"
  11. def test_get_tables():
  12. """测试获取表列表API"""
  13. # 测试数据
  14. test_cases = [
  15. {
  16. "name": "测试默认schema(public)",
  17. "payload": {
  18. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db"
  19. },
  20. "expected_schemas": ["public"]
  21. },
  22. {
  23. "name": "测试指定单个schema",
  24. "payload": {
  25. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  26. "schema": "public"
  27. },
  28. "expected_schemas": ["public"]
  29. },
  30. {
  31. "name": "测试多个schema",
  32. "payload": {
  33. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  34. "schema": "public,information_schema"
  35. },
  36. "expected_schemas": ["public", "information_schema"]
  37. },
  38. {
  39. "name": "测试空schema参数",
  40. "payload": {
  41. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  42. "schema": ""
  43. },
  44. "expected_schemas": ["public"]
  45. }
  46. ]
  47. print("🧪 开始测试表检查API")
  48. print("=" * 50)
  49. for i, test_case in enumerate(test_cases, 1):
  50. print(f"\n{i}. {test_case['name']}")
  51. print("-" * 30)
  52. try:
  53. # 发送请求
  54. response = requests.post(
  55. f"{API_BASE_URL}{ENDPOINT}",
  56. json=test_case["payload"],
  57. headers={"Content-Type": "application/json"},
  58. timeout=30
  59. )
  60. print(f"📤 请求: {json.dumps(test_case['payload'], ensure_ascii=False)}")
  61. print(f"📊 状态码: {response.status_code}")
  62. if response.status_code == 200:
  63. data = response.json()
  64. if data.get("success"):
  65. result_data = data.get("data", {})
  66. tables = result_data.get("tables", [])
  67. schemas = result_data.get("schemas", [])
  68. print(f"✅ 成功")
  69. print(f"📋 返回表数量: {len(tables)}")
  70. print(f"🏷️ 查询的schemas: {schemas}")
  71. print(f"📝 前5个表: {tables[:5]}")
  72. # 验证schema
  73. if schemas == test_case["expected_schemas"]:
  74. print(f"✅ Schema验证通过")
  75. else:
  76. print(f"❌ Schema验证失败: 期望{test_case['expected_schemas']}, 实际{schemas}")
  77. else:
  78. print(f"❌ API返回失败: {data.get('message')}")
  79. else:
  80. print(f"❌ HTTP错误: {response.status_code}")
  81. try:
  82. error_data = response.json()
  83. print(f" 错误信息: {error_data.get('message', 'N/A')}")
  84. except:
  85. print(f" 响应内容: {response.text}")
  86. except requests.exceptions.RequestException as e:
  87. print(f"❌ 请求异常: {e}")
  88. except Exception as e:
  89. print(f"❌ 其他错误: {e}")
  90. def test_error_cases():
  91. """测试错误情况"""
  92. print("\n\n🚨 测试错误情况")
  93. print("=" * 50)
  94. error_test_cases = [
  95. {
  96. "name": "缺少db_connection参数",
  97. "payload": {
  98. "schema": "public"
  99. },
  100. "expected_status": 400
  101. },
  102. {
  103. "name": "无效的数据库连接",
  104. "payload": {
  105. "db_connection": "postgresql://invalid:invalid@localhost:5432/invalid"
  106. },
  107. "expected_status": 500
  108. }
  109. ]
  110. for i, test_case in enumerate(error_test_cases, 1):
  111. print(f"\n{i}. {test_case['name']}")
  112. print("-" * 30)
  113. try:
  114. response = requests.post(
  115. f"{API_BASE_URL}{ENDPOINT}",
  116. json=test_case["payload"],
  117. headers={"Content-Type": "application/json"},
  118. timeout=10
  119. )
  120. print(f"📤 请求: {json.dumps(test_case['payload'], ensure_ascii=False)}")
  121. print(f"📊 状态码: {response.status_code}")
  122. if response.status_code == test_case["expected_status"]:
  123. print(f"✅ 错误处理正确")
  124. else:
  125. print(f"❌ 期望状态码{test_case['expected_status']}, 实际{response.status_code}")
  126. # 显示错误信息
  127. try:
  128. error_data = response.json()
  129. print(f"📄 错误信息: {error_data.get('message', 'N/A')}")
  130. except:
  131. print(f"📄 响应内容: {response.text[:200]}")
  132. except requests.exceptions.Timeout:
  133. print(f"⏰ 请求超时(这是预期的,对于无效连接)")
  134. except Exception as e:
  135. print(f"❌ 异常: {e}")
  136. def test_get_table_ddl():
  137. """测试获取表DDL API"""
  138. print("\n\n🧪 测试表DDL生成API")
  139. print("=" * 50)
  140. # 测试数据
  141. test_cases = [
  142. {
  143. "name": "测试DDL格式输出",
  144. "payload": {
  145. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  146. "table": "public.bss_company",
  147. "business_context": "高速公路服务区管理系统",
  148. "type": "ddl"
  149. }
  150. },
  151. {
  152. "name": "测试MD格式输出",
  153. "payload": {
  154. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  155. "table": "public.bss_company",
  156. "business_context": "高速公路服务区管理系统",
  157. "type": "md"
  158. }
  159. },
  160. {
  161. "name": "测试同时输出DDL和MD",
  162. "payload": {
  163. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  164. "table": "public.bss_company",
  165. "business_context": "高速公路服务区管理系统",
  166. "type": "both"
  167. }
  168. },
  169. {
  170. "name": "测试不指定业务上下文",
  171. "payload": {
  172. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  173. "table": "public.bss_company",
  174. "type": "ddl"
  175. }
  176. }
  177. ]
  178. endpoint = "/api/v0/database/table/ddl"
  179. for i, test_case in enumerate(test_cases, 1):
  180. print(f"\n{i}. {test_case['name']}")
  181. print("-" * 30)
  182. try:
  183. # 发送请求
  184. response = requests.post(
  185. f"{API_BASE_URL}{endpoint}",
  186. json=test_case["payload"],
  187. headers={"Content-Type": "application/json"},
  188. timeout=60 # DDL生成可能需要更长时间(LLM调用)
  189. )
  190. print(f"📤 请求: {json.dumps(test_case['payload'], ensure_ascii=False)}")
  191. print(f"📊 状态码: {response.status_code}")
  192. if response.status_code == 200:
  193. data = response.json()
  194. if data.get("success"):
  195. result_data = data.get("data", {})
  196. table_info = result_data.get("table_info", {})
  197. generation_info = result_data.get("generation_info", {})
  198. print(f"✅ 成功")
  199. print(f"📋 表信息: {table_info.get('full_name')} ({table_info.get('field_count')}字段)")
  200. print(f"💡 生成信息: {generation_info}")
  201. # 检查输出内容
  202. output_type = test_case["payload"].get("type", "ddl")
  203. if output_type in ["ddl", "both"] and "ddl" in result_data:
  204. ddl_lines = result_data["ddl"].count('\n')
  205. print(f"🔧 DDL内容: {ddl_lines}行")
  206. # 显示DDL的前几行
  207. ddl_preview = '\n'.join(result_data["ddl"].split('\n')[:3])
  208. print(f" 预览: {ddl_preview}...")
  209. if output_type in ["md", "both"] and "md" in result_data:
  210. md_lines = result_data["md"].count('\n')
  211. print(f"📄 MD内容: {md_lines}行")
  212. # 显示MD的标题行
  213. md_lines_list = result_data["md"].split('\n')
  214. if md_lines_list:
  215. print(f" 标题: {md_lines_list[0]}")
  216. if "fields" in result_data:
  217. print(f"🗂️ 字段数量: {len(result_data['fields'])}")
  218. else:
  219. print(f"❌ API返回失败: {data.get('message')}")
  220. else:
  221. print(f"❌ HTTP错误: {response.status_code}")
  222. try:
  223. error_data = response.json()
  224. print(f" 错误信息: {error_data.get('message', 'N/A')}")
  225. except:
  226. print(f" 响应内容: {response.text[:200]}")
  227. except requests.exceptions.Timeout:
  228. print(f"⏰ 请求超时(LLM处理可能需要较长时间)")
  229. except requests.exceptions.RequestException as e:
  230. print(f"❌ 请求异常: {e}")
  231. except Exception as e:
  232. print(f"❌ 其他错误: {e}")
  233. def test_ddl_error_cases():
  234. """测试DDL API的错误情况"""
  235. print("\n\n🚨 测试DDL API错误情况")
  236. print("=" * 50)
  237. endpoint = "/api/v0/database/table/ddl"
  238. error_test_cases = [
  239. {
  240. "name": "缺少db_connection参数",
  241. "payload": {
  242. "table": "public.test"
  243. },
  244. "expected_status": 400
  245. },
  246. {
  247. "name": "缺少table参数",
  248. "payload": {
  249. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db"
  250. },
  251. "expected_status": 400
  252. },
  253. {
  254. "name": "无效的type参数",
  255. "payload": {
  256. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  257. "table": "public.test",
  258. "type": "invalid"
  259. },
  260. "expected_status": 400
  261. },
  262. {
  263. "name": "不存在的表",
  264. "payload": {
  265. "db_connection": "postgresql://postgres:postgres@192.168.67.1:5432/highway_db",
  266. "table": "public.non_existent_table_12345"
  267. },
  268. "expected_status": 500
  269. }
  270. ]
  271. for i, test_case in enumerate(error_test_cases, 1):
  272. print(f"\n{i}. {test_case['name']}")
  273. print("-" * 30)
  274. try:
  275. response = requests.post(
  276. f"{API_BASE_URL}{endpoint}",
  277. json=test_case["payload"],
  278. headers={"Content-Type": "application/json"},
  279. timeout=10
  280. )
  281. print(f"📤 请求: {json.dumps(test_case['payload'], ensure_ascii=False)}")
  282. print(f"📊 状态码: {response.status_code}")
  283. if response.status_code == test_case["expected_status"]:
  284. print(f"✅ 错误处理正确")
  285. else:
  286. print(f"❌ 期望状态码{test_case['expected_status']}, 实际{response.status_code}")
  287. # 显示错误信息
  288. try:
  289. error_data = response.json()
  290. print(f"📄 错误信息: {error_data.get('message', 'N/A')}")
  291. except:
  292. print(f"📄 响应内容: {response.text[:200]}")
  293. except requests.exceptions.Timeout:
  294. print(f"⏰ 请求超时(这可能是预期的)")
  295. except Exception as e:
  296. print(f"❌ 异常: {e}")
  297. if __name__ == "__main__":
  298. print("🚀 表检查API测试开始")
  299. print(f"🌐 API地址: {API_BASE_URL}")
  300. # 首先测试表列表API
  301. test_get_tables()
  302. # 然后测试表列表API的错误情况
  303. test_error_cases()
  304. # 测试DDL生成API
  305. test_get_table_ddl()
  306. # 测试DDL API的错误情况
  307. test_ddl_error_cases()
  308. print("\n" + "=" * 50)
  309. print("🏁 所有测试完成")
  310. print("\n💡 使用说明:")
  311. print(" - 表列表API: POST /api/v0/database/tables")
  312. print(" - 表DDL API: POST /api/v0/database/table/ddl")
  313. print(" - 如果看到连接错误,请确保数据库服务器可访问")
  314. print(" - DDL生成包含LLM调用,可能需要较长时间")
  315. print(" - 支持三种输出格式:ddl、md、both")