- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
172 lines
6.0 KiB
Python
172 lines
6.0 KiB
Python
"""
|
|
API 测试脚本
|
|
"""
|
|
import asyncio
|
|
import json
|
|
from typing import Optional
|
|
|
|
import httpx
|
|
|
|
# API基础URL
|
|
BASE_URL = "http://localhost:8000/api/v1"
|
|
|
|
|
|
class APITester:
|
|
def __init__(self):
|
|
self.client = httpx.AsyncClient(base_url=BASE_URL)
|
|
self.token: Optional[str] = None
|
|
|
|
async def login(self, username: str, password: str):
|
|
"""测试登录"""
|
|
print(f"\n1. 测试登录 - 用户: {username}")
|
|
response = await self.client.post("/auth/login", json={
|
|
"username": username,
|
|
"password": password
|
|
})
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
self.token = data["data"]["token"]["access_token"]
|
|
print(f"✓ 登录成功!")
|
|
print(f" 用户信息: {data['data']['user']['username']} ({data['data']['user']['role']})")
|
|
print(f" 令牌: {self.token[:20]}...")
|
|
return True
|
|
else:
|
|
print(f"✗ 登录失败: {response.status_code}")
|
|
print(f" 错误信息: {response.json()}")
|
|
return False
|
|
|
|
async def get_current_user(self):
|
|
"""测试获取当前用户"""
|
|
print("\n2. 测试获取当前用户信息")
|
|
headers = {"Authorization": f"Bearer {self.token}"}
|
|
response = await self.client.get("/users/me", headers=headers)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
print(f"✓ 获取成功!")
|
|
print(f" 用户: {data['data']['username']}")
|
|
print(f" 邮箱: {data['data']['email']}")
|
|
print(f" 角色: {data['data']['role']}")
|
|
else:
|
|
print(f"✗ 获取失败: {response.status_code}")
|
|
print(f" 错误信息: {response.json()}")
|
|
|
|
async def list_users(self):
|
|
"""测试获取用户列表"""
|
|
print("\n3. 测试获取用户列表")
|
|
headers = {"Authorization": f"Bearer {self.token}"}
|
|
response = await self.client.get("/users?page=1&page_size=10", headers=headers)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
print(f"✓ 获取成功!")
|
|
print(f" 总数: {data['data']['total']}")
|
|
print(f" 用户列表:")
|
|
for user in data['data']['items']:
|
|
print(f" - {user['username']} ({user['role']}) - {user['email']}")
|
|
else:
|
|
print(f"✗ 获取失败: {response.status_code}")
|
|
print(f" 错误信息: {response.json()}")
|
|
|
|
async def create_user(self):
|
|
"""测试创建用户(需要管理员权限)"""
|
|
print("\n4. 测试创建用户(需要管理员权限)")
|
|
headers = {"Authorization": f"Bearer {self.token}"}
|
|
new_user = {
|
|
"username": "testuser",
|
|
"email": "testuser@example.com",
|
|
"password": "test123456",
|
|
"full_name": "测试用户",
|
|
"role": "trainee"
|
|
}
|
|
|
|
response = await self.client.post("/users", json=new_user, headers=headers)
|
|
|
|
if response.status_code == 201:
|
|
data = response.json()
|
|
print(f"✓ 创建成功!")
|
|
print(f" 新用户: {data['data']['username']} - {data['data']['email']}")
|
|
else:
|
|
print(f"✗ 创建失败: {response.status_code}")
|
|
print(f" 错误信息: {response.json()}")
|
|
|
|
async def update_password(self):
|
|
"""测试修改密码"""
|
|
print("\n5. 测试修改密码")
|
|
headers = {"Authorization": f"Bearer {self.token}"}
|
|
|
|
# 先尝试错误的旧密码
|
|
response = await self.client.put("/users/me/password", json={
|
|
"old_password": "wrongpassword",
|
|
"new_password": "newpass123"
|
|
}, headers=headers)
|
|
|
|
if response.status_code != 200:
|
|
print(f"✓ 正确拒绝了错误的旧密码")
|
|
|
|
# 使用正确的旧密码
|
|
response = await self.client.put("/users/me/password", json={
|
|
"old_password": "admin123", # 假设是admin用户
|
|
"new_password": "admin123" # 改回原密码
|
|
}, headers=headers)
|
|
|
|
if response.status_code == 200:
|
|
print(f"✓ 密码修改成功!")
|
|
else:
|
|
print(f" 注意: 密码修改测试可能因为旧密码不匹配而失败")
|
|
|
|
async def test_unauthorized(self):
|
|
"""测试未授权访问"""
|
|
print("\n6. 测试未授权访问")
|
|
# 不带token访问需要认证的接口
|
|
response = await self.client.get("/users/me")
|
|
|
|
if response.status_code == 403:
|
|
print(f"✓ 正确拒绝了未授权访问")
|
|
else:
|
|
print(f"✗ 未授权访问测试失败: {response.status_code}")
|
|
|
|
async def close(self):
|
|
"""关闭客户端"""
|
|
await self.client.aclose()
|
|
|
|
|
|
async def main():
|
|
"""主测试函数"""
|
|
print("=================================")
|
|
print("考培练系统 API 测试")
|
|
print("=================================")
|
|
|
|
tester = APITester()
|
|
|
|
try:
|
|
# 测试未授权访问
|
|
await tester.test_unauthorized()
|
|
|
|
# 测试管理员登录
|
|
print("\n--- 管理员测试 ---")
|
|
if await tester.login("admin", "admin123"):
|
|
await tester.get_current_user()
|
|
await tester.list_users()
|
|
await tester.create_user()
|
|
await tester.update_password()
|
|
|
|
# 测试普通用户登录
|
|
print("\n\n--- 普通用户测试 ---")
|
|
if await tester.login("trainee1", "trainee123"):
|
|
await tester.get_current_user()
|
|
await tester.list_users()
|
|
await tester.create_user() # 应该失败(权限不足)
|
|
|
|
print("\n\n测试完成!")
|
|
|
|
except Exception as e:
|
|
print(f"\n错误: {str(e)}")
|
|
print("提示: 请确保服务器正在运行 (http://localhost:8000)")
|
|
finally:
|
|
await tester.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main()) |