2025-09-11 20:25:05 +08:00
|
|
|
|
import requests
|
|
|
|
|
import json
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
# API基础URL
|
|
|
|
|
BASE_URL = "http://localhost:8100/RuYuanZaiYuan"
|
2025-09-11 21:23:39 +08:00
|
|
|
|
EDUCATION_DATA_BASE_URL = "http://localhost:8100/EducationData"
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
|
|
|
|
# 支持的教育阶段
|
|
|
|
|
test_education_stages = [
|
|
|
|
|
("preschool", "学前"),
|
|
|
|
|
("primary", "小学"),
|
|
|
|
|
("junior", "初中"),
|
|
|
|
|
("senior", "高中")
|
|
|
|
|
]
|
|
|
|
|
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# 测试年份
|
|
|
|
|
test_years = [2023, 2022, 2024]
|
|
|
|
|
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
|
|
|
|
def test_school_chart_interface():
|
|
|
|
|
"""测试获取教育阶段图表数据接口"""
|
|
|
|
|
print("\n===== 测试 /school/chart 接口 =====")
|
|
|
|
|
|
|
|
|
|
for stage_code, stage_name in test_education_stages:
|
|
|
|
|
url = f"{BASE_URL}/school/chart?education_stage={stage_code}"
|
|
|
|
|
print(f"\n测试 {stage_name}({stage_code}) 数据:")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
response = requests.get(url)
|
|
|
|
|
response.raise_for_status() # 如果状态码不是200,抛出异常
|
|
|
|
|
|
|
|
|
|
data = response.json()
|
|
|
|
|
print(f"响应状态码: {response.status_code}")
|
|
|
|
|
print(f"响应数据: {json.dumps(data, ensure_ascii=False, indent=2)}")
|
|
|
|
|
|
|
|
|
|
# 验证返回数据的基本结构
|
|
|
|
|
assert "xAxis_data" in data, "返回数据缺少xAxis_data字段"
|
|
|
|
|
assert "series_data_0" in data, "返回数据缺少series_data_0字段(城区数据)"
|
|
|
|
|
assert "series_data_1" in data, "返回数据缺少series_data_1字段(镇区数据)"
|
|
|
|
|
assert "series_data_2" in data, "返回数据缺少series_data_2字段(乡村数据)"
|
|
|
|
|
assert "series_data_3" in data, "返回数据缺少series_data_3字段(总人数数据)"
|
|
|
|
|
assert "series_data_4" in data, "返回数据缺少series_data_4字段(2022年基数数据)"
|
|
|
|
|
assert "education_stage" in data, "返回数据缺少education_stage字段"
|
|
|
|
|
assert data["education_stage"] == stage_name, f"教育阶段名称不匹配,期望: {stage_name},实际: {data['education_stage']}"
|
|
|
|
|
|
|
|
|
|
print(f"✅ {stage_name} 数据验证通过")
|
|
|
|
|
|
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
|
print(f"❌ 请求失败: {e}")
|
|
|
|
|
except AssertionError as e:
|
|
|
|
|
print(f"❌ 数据验证失败: {e}")
|
|
|
|
|
|
|
|
|
|
# 添加短暂延迟,避免请求过于频繁
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
|
|
|
|
|
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# @router.get("/school/inschool/chart")
|
|
|
|
|
# async def get_in_school_chart_config(
|
|
|
|
|
# education_stage: str = Query(default="preschool", pattern="^(preschool|primary|junior|senior)$",
|
|
|
|
|
# description="教育阶段: preschool(学前), primary(小学), junior(初中), senior(高中)")
|
|
|
|
|
# ):
|
|
|
|
|
# return RuYuanZaiYuanModel.generate_in_school_education_config(education_stage)
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_education_data_by_year():
|
|
|
|
|
"""测试获取指定年份教育数据接口"""
|
|
|
|
|
print("\n===== 测试 /EducationData/byYear 接口 =====")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# 测试不同年份的数据
|
|
|
|
|
for year in test_years:
|
|
|
|
|
url = f"{EDUCATION_DATA_BASE_URL}/byYear?year={year}"
|
|
|
|
|
print(f"\n测试 {year} 年数据:")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
response = requests.get(url)
|
|
|
|
|
response.raise_for_status() # 如果状态码不是200,抛出异常
|
|
|
|
|
|
|
|
|
|
data = response.json()
|
|
|
|
|
print(f"响应状态码: {response.status_code}")
|
|
|
|
|
print(f"响应数据: {json.dumps(data, ensure_ascii=False, indent=2)}")
|
|
|
|
|
|
|
|
|
|
# 验证返回数据的基本结构
|
2025-09-11 21:23:39 +08:00
|
|
|
|
assert "code" in data, "返回数据缺少code字段"
|
|
|
|
|
assert "message" in data, "返回数据缺少message字段"
|
|
|
|
|
assert "data" in data, "返回数据缺少data字段"
|
|
|
|
|
assert data["code"] == 200, f"状态码不匹配,期望: 200,实际: {data['code']}"
|
|
|
|
|
assert isinstance(data["data"], list), "data字段应为列表类型"
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# 验证数据内容
|
|
|
|
|
if data["data"]:
|
|
|
|
|
# 检查每个数据项的结构
|
|
|
|
|
for item in data["data"]:
|
|
|
|
|
assert "education_stage" in item, "数据项缺少education_stage字段"
|
|
|
|
|
assert "school_count" in item, "数据项缺少school_count字段"
|
|
|
|
|
assert "teacher_count_10k" in item, "数据项缺少teacher_count_10k字段"
|
|
|
|
|
assert "enrollment_count_10k" in item, "数据项缺少enrollment_count_10k字段"
|
|
|
|
|
assert "admission_count_10k" in item, "数据项缺少admission_count_10k字段"
|
|
|
|
|
|
|
|
|
|
# 检查数值类型
|
|
|
|
|
assert isinstance(item["school_count"], (int, float)), "school_count应为数值类型"
|
|
|
|
|
assert isinstance(item["teacher_count_10k"], (int, float)), "teacher_count_10k应为数值类型"
|
|
|
|
|
assert isinstance(item["enrollment_count_10k"], (int, float)), "enrollment_count_10k应为数值类型"
|
|
|
|
|
assert isinstance(item["admission_count_10k"], (int, float)), "admission_count_10k应为数值类型"
|
|
|
|
|
|
|
|
|
|
print(f"✅ {year} 年数据验证通过,共包含 {len(data['data'])} 个教育阶段的数据")
|
|
|
|
|
else:
|
|
|
|
|
print(f"⚠️ {year} 年未返回数据")
|
|
|
|
|
|
2025-09-11 20:25:05 +08:00
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
|
print(f"❌ 请求失败: {e}")
|
|
|
|
|
except AssertionError as e:
|
|
|
|
|
print(f"❌ 数据验证失败: {e}")
|
|
|
|
|
|
|
|
|
|
# 添加短暂延迟,避免请求过于频繁
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# 测试边界值
|
|
|
|
|
print("\n===== 测试边界值 =====")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# 测试最小值年份
|
|
|
|
|
min_year = 2015
|
|
|
|
|
url = f"{EDUCATION_DATA_BASE_URL}/byYear?year={min_year}"
|
|
|
|
|
print(f"\n测试最小值年份 {min_year}:")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
try:
|
|
|
|
|
response = requests.get(url)
|
|
|
|
|
response.raise_for_status()
|
2025-09-11 21:23:39 +08:00
|
|
|
|
print(f"响应状态码: {response.status_code}")
|
|
|
|
|
print(f"✅ 最小值年份测试通过")
|
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
|
print(f"❌ 请求失败: {e}")
|
|
|
|
|
|
|
|
|
|
# 测试最大值年份
|
|
|
|
|
max_year = 2028
|
|
|
|
|
url = f"{EDUCATION_DATA_BASE_URL}/byYear?year={max_year}"
|
|
|
|
|
print(f"\n测试最大值年份 {max_year}:")
|
|
|
|
|
try:
|
2025-09-11 20:25:05 +08:00
|
|
|
|
response = requests.get(url)
|
|
|
|
|
response.raise_for_status()
|
2025-09-11 21:23:39 +08:00
|
|
|
|
print(f"响应状态码: {response.status_code}")
|
|
|
|
|
print(f"✅ 最大值年份测试通过")
|
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
|
print(f"❌ 请求失败: {e}")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# 测试超出范围的年份
|
|
|
|
|
invalid_year = 2030
|
|
|
|
|
url = f"{EDUCATION_DATA_BASE_URL}/byYear?year={invalid_year}"
|
|
|
|
|
print(f"\n测试超出范围的年份 {invalid_year}:")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
try:
|
|
|
|
|
response = requests.get(url)
|
2025-09-11 21:23:39 +08:00
|
|
|
|
if response.status_code == 422: # FastAPI的验证错误状态码
|
|
|
|
|
print(f"响应状态码: {response.status_code}")
|
|
|
|
|
print(f"✅ 超出范围年份正确返回验证错误")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
else:
|
2025-09-11 21:23:39 +08:00
|
|
|
|
print(f"❌ 期望状态码422,实际: {response.status_code}")
|
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
|
|
print(f"❌ 请求失败: {e}")
|
2025-09-11 20:25:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2025-09-11 21:23:39 +08:00
|
|
|
|
# 测试原有接口
|
|
|
|
|
# test_school_chart_interface()
|
|
|
|
|
|
|
|
|
|
# 测试新添加的教育数据接口
|
|
|
|
|
test_education_data_by_year()
|