Files
gym-manage/test-suite/tests/uat/test_uat_acceptance.py

1279 lines
56 KiB
Python

"""
UAT用户验收测试套件
测试范围:
1. 业务场景完整性验证
2. 用户角色权限配置验证
3. 系统配置验证
4. 数据字典验证
5. 通知公告验证
6. 文件管理验证
7. 审计日志验证
8. 用户体验验证
9. 性能验收验证
10. 安全验收验证
"""
import pytest
import time
import uuid
import asyncio
from typing import Dict, Any
from api.auth_api import AuthAPI
from api.user_api import UserAPI
from api.role_api import RoleAPI
from api.menu_api import MenuAPI
from api.dict_api import DictAPI
from api.config_api import ConfigAPI
from api.notice_api import SysNoticeAPI
from api.file_api import FileAPI
from api.audit_api import AuditAPI
from config.settings import settings
@pytest.mark.uat
@pytest.mark.acceptance
@pytest.mark.regression
class TestUATAcceptance:
"""用户验收测试类 - 模拟真实业务场景"""
@pytest.mark.asyncio
async def test_uat_user_management_business_scenario(
self, authenticated_client, test_data_manager
):
"""
UAT-01: 用户管理业务场景验证
场景描述:
- 系统管理员创建新员工账户
- 分配相应角色和权限
- 员工登录系统并访问授权资源
- 员工信息变更处理
- 员工离职账户禁用
"""
user_api = UserAPI(authenticated_client)
role_api = RoleAPI(authenticated_client)
unique_id = f"uat_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 创建普通员工角色
employee_role_data = {
"roleName": f"UAT_Employee_Role_{unique_id}",
"roleKey": f"uat_employee_role_{unique_id}",
"roleSort": 10,
"status": 1,
"remark": "UAT测试-普通员工角色"
}
employee_role_response = await role_api.create_role(employee_role_data)
assert employee_role_response.status_code == 201, "创建员工角色失败"
employee_role_id = employee_role_response.json()["id"]
test_data_manager.add_role(employee_role_id)
# 步骤2: 创建部门经理角色
manager_role_data = {
"roleName": f"UAT_Manager_Role_{unique_id}",
"roleKey": f"uat_manager_role_{unique_id}",
"roleSort": 9,
"status": 1,
"remark": "UAT测试-部门经理角色"
}
manager_role_response = await role_api.create_role(manager_role_data)
assert manager_role_response.status_code == 201, "创建经理角色失败"
manager_role_id = manager_role_response.json()["id"]
test_data_manager.add_role(manager_role_id)
# 步骤3: 创建新员工账户(模拟入职)
new_employee_data = {
"username": f"uat_employee_{unique_id}",
"password": "Employee123!@#",
"email": f"employee_{unique_id}@company.com",
"roleId": employee_role_id,
"status": 1,
"remark": "UAT测试-新入职员工"
}
new_employee_response = await user_api.create_user(new_employee_data)
assert new_employee_response.status_code == 201, "创建新员工账户失败"
employee_id = new_employee_response.json()["id"]
test_data_manager.add_user(employee_id)
# 步骤4: 验证员工可以登录
login_response = await AuthAPI(authenticated_client).login(
f"uat_employee_{unique_id}", "Employee123!@#"
)
assert login_response.status_code == 200, "员工登录失败"
login_data = login_response.json()
assert "token" in login_data, "登录响应缺少token"
# 步骤5: 员工获取个人资料(使用已知用户ID)
profile_response = await user_api.get_user_by_id(employee_id)
assert profile_response.status_code == 200, "获取个人资料失败"
profile_data = profile_response.json()
assert profile_data["username"] == f"uat_employee_{unique_id}", "个人资料不匹配"
# 步骤6: 员工修改个人信息(使用已知用户ID)
update_profile_data = {
"nickname": f"张三_{unique_id}",
"phone": f"1380013800{unique_id[-4:]}",
"remark": "UAT测试-更新个人信息"
}
update_profile_response = await user_api.update_user(employee_id, update_profile_data)
assert update_profile_response.status_code == 200, "更新个人资料失败"
# 步骤7: 员工晋升为部门经理(角色变更)
assign_roles_response = await user_api.assign_roles(employee_id, [manager_role_id])
assert assign_roles_response.status_code == 200, "角色变更失败"
# 步骤8: 验证角色变更生效
user_detail_response = await user_api.get_user_by_id(employee_id)
assert user_detail_response.status_code == 200, "获取用户详情失败"
user_detail = user_detail_response.json()
assert manager_role_id in user_detail["roles"], "角色变更未生效"
# 步骤9: 员工离职(禁用账户)
disable_data = {"status": 0}
disable_response = await user_api.update_user(employee_id, disable_data)
assert disable_response.status_code == 200, "禁用账户失败"
# 步骤10: 验证已禁用账户无法登录
disabled_login_response = await AuthAPI(authenticated_client).login(
f"uat_employee_{unique_id}", "Employee123!@#"
)
assert disabled_login_response.status_code != 200, "已禁用账户不应能登录"
# 清理
await user_api.delete_user(employee_id)
test_data_manager._users.remove(employee_id)
await role_api.delete_role(manager_role_id)
test_data_manager._roles.remove(manager_role_id)
await role_api.delete_role(employee_role_id)
test_data_manager._roles.remove(employee_role_id)
@pytest.mark.asyncio
async def test_uat_role_permission_configuration(
self, authenticated_client, test_data_manager
):
"""
UAT-02: 角色权限配置验证
场景描述:
- 创建不同级别的角色(管理员、经理、普通员工)
- 为每个角色配置不同的菜单和数据权限
- 验证权限隔离
- 验证权限继承
"""
role_api = RoleAPI(authenticated_client)
menu_api = MenuAPI(authenticated_client)
unique_id = f"uat_role_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 创建系统管理员角色
admin_role_data = {
"roleName": f"UAT_Admin_Role_{unique_id}",
"roleKey": f"uat_admin_role_{unique_id}",
"roleSort": 1,
"status": 1,
"remark": "UAT测试-系统管理员角色"
}
admin_role_response = await role_api.create_role(admin_role_data)
assert admin_role_response.status_code == 201, "创建管理员角色失败"
admin_role_id = admin_role_response.json()["id"]
test_data_manager.add_role(admin_role_id)
# 步骤2: 创建业务经理角色
manager_role_data = {
"roleName": f"UAT_Business_Role_{unique_id}",
"roleKey": f"uat_business_role_{unique_id}",
"roleSort": 5,
"status": 1,
"remark": "UAT测试-业务经理角色"
}
manager_role_response = await role_api.create_role(manager_role_data)
assert manager_role_response.status_code == 201, "创建业务经理角色失败"
manager_role_id = manager_role_response.json()["id"]
test_data_manager.add_role(manager_role_id)
# 步骤3: 创建普通员工角色
employee_role_data = {
"roleName": f"UAT_Staff_Role_{unique_id}",
"roleKey": f"uat_staff_role_{unique_id}",
"roleSort": 10,
"status": 1,
"remark": "UAT测试-普通员工角色"
}
employee_role_response = await role_api.create_role(employee_role_data)
assert employee_role_response.status_code == 201, "创建普通员工角色失败"
employee_role_id = employee_role_response.json()["id"]
test_data_manager.add_role(employee_role_id)
# 步骤4: 创建系统管理菜单
system_menu_data = {
"parentId": 0,
"menuName": f"系统管理_{unique_id}",
"menuType": "M",
"orderNum": 1,
"component": "Layout",
"perms": f"system:{unique_id}",
"status": 1,
"icon": "system"
}
system_menu_response = await menu_api.create_menu(system_menu_data)
assert system_menu_response.status_code == 201, "创建系统管理菜单失败"
system_menu_id = system_menu_response.json()["id"]
test_data_manager.add_menu(system_menu_id)
# 步骤5: 创建用户管理子菜单
user_menu_data = {
"parentId": system_menu_id,
"menuName": "用户管理",
"menuType": "C",
"orderNum": 1,
"component": "UserManagement",
"perms": f"user:manage:{unique_id}",
"status": 1
}
user_menu_response = await menu_api.create_menu(user_menu_data)
assert user_menu_response.status_code == 201, "创建用户管理菜单失败"
user_menu_id = user_menu_response.json()["id"]
test_data_manager.add_menu(user_menu_id)
# 步骤6: 创建角色管理子菜单
role_menu_data = {
"parentId": system_menu_id,
"menuName": "角色管理",
"menuType": "C",
"orderNum": 2,
"component": "RoleManagement",
"perms": f"role:manage:{unique_id}",
"status": 1
}
role_menu_response = await menu_api.create_menu(role_menu_data)
assert role_menu_response.status_code == 201, "创建角色管理菜单失败"
role_menu_id = role_menu_response.json()["id"]
test_data_manager.add_menu(role_menu_id)
# 步骤7: 为管理员角色分配所有菜单权限
admin_permission_data = {"menuIds": [system_menu_id, user_menu_id, role_menu_id]}
admin_permission_response = await role_api.assign_permissions(admin_role_id, admin_permission_data)
assert admin_permission_response.status_code == 200, "为管理员分配权限失败"
# 步骤8: 为业务经理角色分配部分菜单权限
manager_permission_data = {"menuIds": [user_menu_id]}
manager_permission_response = await role_api.assign_permissions(manager_role_id, manager_permission_data)
assert manager_permission_response.status_code == 200, "为业务经理分配权限失败"
# 步骤9: 为普通员工角色分配最小权限
employee_permission_data = {"menuIds": []}
employee_permission_response = await role_api.assign_permissions(employee_role_id, employee_permission_data)
assert employee_permission_response.status_code == 200, "为普通员工分配权限失败"
# 步骤10: 验证管理员可以访问所有菜单
admin_menus_response = await menu_api.get_user_menus_by_role(admin_role_id)
assert admin_menus_response.status_code == 200, "获取管理员菜单失败"
admin_menus = admin_menus_response.json()
assert len(admin_menus) >= 3, "管理员应能访问至少3个菜单"
# 步骤11: 验证业务经理只能访问授权菜单
manager_menus_response = await menu_api.get_user_menus_by_role(manager_role_id)
assert manager_menus_response.status_code == 200, "获取业务经理菜单失败"
manager_menus = manager_menus_response.json()
assert len(manager_menus) == 1, "业务经理应只能访问1个菜单"
assert manager_menus[0]["id"] == user_menu_id, "业务经理菜单权限不正确"
# 步骤12: 验证普通员工无菜单权限
employee_menus_response = await menu_api.get_user_menus_by_role(employee_role_id)
assert employee_menus_response.status_code == 200, "获取普通员工菜单失败"
employee_menus = employee_menus_response.json()
assert len(employee_menus) == 0, "普通员工应无菜单权限"
# 清理
await role_api.assign_permissions(admin_role_id, {"menuIds": []})
await role_api.assign_permissions(manager_role_id, {"menuIds": []})
await role_api.assign_permissions(employee_role_id, {"menuIds": []})
await menu_api.delete_menu(role_menu_id)
test_data_manager._menus.remove(role_menu_id)
await menu_api.delete_menu(user_menu_id)
test_data_manager._menus.remove(user_menu_id)
await menu_api.delete_menu(system_menu_id)
test_data_manager._menus.remove(system_menu_id)
await role_api.delete_role(employee_role_id)
test_data_manager._roles.remove(employee_role_id)
await role_api.delete_role(manager_role_id)
test_data_manager._roles.remove(manager_role_id)
await role_api.delete_role(admin_role_id)
test_data_manager._roles.remove(admin_role_id)
@pytest.mark.asyncio
async def test_uat_system_configuration_validation(
self, authenticated_client, test_data_manager
):
"""
UAT-03: 系统配置验证
场景描述:
- 修改系统基本配置
- 验证配置生效
- 修改邮件配置
- 验证配置有效性
- 配置回滚
"""
config_api = ConfigAPI(authenticated_client)
unique_id = f"uat_config_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 获取当前系统配置
config_list_response = await config_api.get_config_list(page=0, size=100)
assert config_list_response.status_code == 200, "获取系统配置列表失败"
config_list = config_list_response.json()
# 步骤2: 创建测试配置项
test_config_data = {
"configKey": f"uat_test_key_{unique_id}",
"configName": f"UAT测试配置_{unique_id}",
"configType": "Y",
"configValue": "test_value_initial",
"remark": "UAT测试-系统配置验证"
}
test_config_response = await config_api.create_config(test_config_data)
assert test_config_response.status_code == 201, "创建测试配置失败"
test_config_id = test_config_response.json()["id"]
test_data_manager.add_config(test_config_id)
# 步骤3: 验证配置创建成功
get_config_response = await config_api.get_config_by_key(f"uat_test_key_{unique_id}")
assert get_config_response.status_code == 200, "获取测试配置失败"
get_config_data = get_config_response.json()
assert get_config_data["configValue"] == "test_value_initial", "配置值不匹配"
# 步骤4: 更新配置值
update_config_data = {
"configValue": "test_value_updated",
"remark": "UAT测试-更新配置值"
}
update_config_response = await config_api.update_config(test_config_id, update_config_data)
assert update_config_response.status_code == 200, "更新配置失败"
# 步骤5: 验证配置更新生效
verify_config_response = await config_api.get_config_by_key(f"uat_test_key_{unique_id}")
assert verify_config_response.status_code == 200, "验证配置更新失败"
verify_config_data = verify_config_response.json()
assert verify_config_data["configValue"] == "test_value_updated", "配置更新未生效"
# 步骤6: 创建邮件配置
email_config_data = {
"configKey": f"uat_email_config_{unique_id}",
"configName": "UAT测试邮件配置",
"configType": "Y",
"configValue": '{"host":"smtp.test.com","port":587,"username":"test@test.com","password":"test123"}',
"remark": "UAT测试-邮件配置"
}
email_config_response = await config_api.create_config(email_config_data)
assert email_config_response.status_code == 201, "创建邮件配置失败"
email_config_id = email_config_response.json()["id"]
test_data_manager.add_config(email_config_id)
# 步骤7: 验证邮件配置格式
email_config_get_response = await config_api.get_config_by_key(f"uat_email_config_{unique_id}")
assert email_config_get_response.status_code == 200, "获取邮件配置失败"
email_config = email_config_get_response.json()
import json
email_config_value = json.loads(email_config["configValue"])
assert "host" in email_config_value, "邮件配置缺少host字段"
assert "port" in email_config_value, "邮件配置缺少port字段"
# 步骤8: 修改邮件配置
updated_email_config = {
"configValue": '{"host":"smtp.updated.com","port":465,"username":"updated@test.com","password":"updated123"}',
"remark": "UAT测试-更新邮件配置"
}
updated_email_config_response = await config_api.update_config(email_config_id, updated_email_config)
assert updated_email_config_response.status_code == 200, "更新邮件配置失败"
# 步骤9: 验证邮件配置更新
verify_email_config_response = await config_api.get_config_by_key(f"uat_email_config_{unique_id}")
assert verify_email_config_response.status_code == 200, "验证邮件配置更新失败"
verify_email_config = verify_email_config_response.json()
verify_email_value = json.loads(verify_email_config["configValue"])
assert verify_email_value["host"] == "smtp.updated.com", "邮件配置更新未生效"
# 步骤10: 删除测试配置
await config_api.delete_config(test_config_id)
test_data_manager._configs.remove(test_config_id)
# 步骤11: 删除邮件配置
await config_api.delete_config(email_config_id)
test_data_manager._configs.remove(email_config_id)
@pytest.mark.asyncio
async def test_uat_dictionary_management(
self, authenticated_client, test_data_manager
):
"""
UAT-04: 数据字典验证
场景描述:
- 创建字典类型
- 添加字典数据
- 修改字典数据
- 删除字典数据
- 验证字典缓存
"""
dict_api = DictAPI(authenticated_client)
unique_id = f"uat_dict_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 创建用户状态字典类型
status_type_data = {
"type": f"USER_STATUS_{unique_id}",
"name": "用户状态",
"remark": "UAT测试-用户状态字典",
"sort": 1
}
status_type_response = await dict_api.create_type(status_type_data)
assert status_type_response.status_code == 201, "创建用户状态字典类型失败"
status_type_id = status_type_response.json()["id"]
test_data_manager.add_dict_type(status_type_id)
# 步骤2: 添加启用状态数据
enabled_status_data = {
"type": f"USER_STATUS_{unique_id}",
"code": "ENABLED",
"name": "启用",
"value": "1",
"remark": "用户已启用",
"sort": 1
}
enabled_status_response = await dict_api.create(enabled_status_data)
assert enabled_status_response.status_code == 201, "添加启用状态失败"
enabled_status_id = enabled_status_response.json()["id"]
test_data_manager.add_dict(enabled_status_id)
# 步骤3: 添加禁用状态数据
disabled_status_data = {
"type": f"USER_STATUS_{unique_id}",
"code": "DISABLED",
"name": "禁用",
"value": "0",
"remark": "用户已禁用",
"sort": 2
}
disabled_status_response = await dict_api.create(disabled_status_data)
assert disabled_status_response.status_code == 201, "添加禁用状态失败"
disabled_status_id = disabled_status_response.json()["id"]
test_data_manager.add_dict(disabled_status_id)
# 步骤4: 创建用户类型字典
user_type_data = {
"type": f"USER_TYPE_{unique_id}",
"name": "用户类型",
"remark": "UAT测试-用户类型字典",
"sort": 2
}
user_type_response = await dict_api.create_type(user_type_data)
assert user_type_response.status_code == 201, "创建用户类型字典失败"
user_type_id = user_type_response.json()["id"]
test_data_manager.add_dict_type(user_type_id)
# 步骤5: 添加普通用户类型
normal_type_data = {
"type": f"USER_TYPE_{unique_id}",
"code": "NORMAL",
"name": "普通用户",
"value": "1",
"remark": "普通注册用户",
"sort": 1
}
normal_type_response = await dict_api.create(normal_type_data)
assert normal_type_response.status_code == 201, "添加普通用户类型失败"
normal_type_id = normal_type_response.json()["id"]
test_data_manager.add_dict(normal_type_id)
# 步骤6: 添加管理员类型
admin_type_data = {
"type": f"USER_TYPE_{unique_id}",
"code": "ADMIN",
"name": "管理员",
"value": "2",
"remark": "系统管理员",
"sort": 2
}
admin_type_response = await dict_api.create(admin_type_data)
assert admin_type_response.status_code == 201, "添加管理员类型失败"
admin_type_id = admin_type_response.json()["id"]
test_data_manager.add_dict(admin_type_id)
# 步骤7: 修改字典数据
update_status_data = {
"name": "已启用",
"remark": "UAT测试-更新启用状态描述"
}
update_status_response = await dict_api.update_dict(enabled_status_id, update_status_data)
assert update_status_response.status_code == 200, "更新字典数据失败"
# 步骤8: 验证字典数据更新
verify_status_response = await dict_api.get_dict_by_id(enabled_status_id)
assert verify_status_response.status_code == 200, "验证字典数据失败"
verify_status_data = verify_status_response.json()
assert verify_status_data["name"] == "已启用", "字典数据更新未生效"
# 步骤9: 查询字典类型列表
type_list_response = await dict_api.get_type_list(page=0, size=10)
assert type_list_response.status_code == 200, "获取字典类型列表失败"
type_list = type_list_response.json()
assert any(t["type"] == f"USER_STATUS_{unique_id}" for t in type_list), "字典类型未创建成功"
# 步骤10: 查询字典数据列表
data_list_response = await dict_api.get_dict_list(page=0, size=10)
assert data_list_response.status_code == 200, "获取字典数据列表失败"
data_list = data_list_response.json()
assert len(data_list["content"]) >= 5, "字典数据数量不足"
# 清理
await dict_api.delete_dict(admin_type_id)
test_data_manager._dicts.remove(admin_type_id)
await dict_api.delete_dict(normal_type_id)
test_data_manager._dicts.remove(normal_type_id)
await dict_api.delete_type(user_type_id)
test_data_manager._dict_types.remove(user_type_id)
await dict_api.delete_dict(disabled_status_id)
test_data_manager._dicts.remove(disabled_status_id)
await dict_api.delete_dict(enabled_status_id)
test_data_manager._dicts.remove(enabled_status_id)
await dict_api.delete_type(status_type_id)
test_data_manager._dict_types.remove(status_type_id)
@pytest.mark.asyncio
async def test_uat_notice_management(
self, authenticated_client, test_data_manager
):
"""
UAT-05: 通知公告验证
场景描述:
- 创建系统通知
- 发布通知
- 查看通知
- 更新通知
- 删除通知
"""
notice_api = SysNoticeAPI(authenticated_client)
unique_id = f"uat_notice_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 创建系统通知
notice_data = {
"noticeTitle": f"系统维护通知_{unique_id}",
"noticeType": "1",
"noticeContent": f"""
<h1>系统维护通知</h1>
<p>尊敬的用户:</p>
<p>为提升系统性能,我们将于以下时间进行系统维护:</p>
<ul>
<li>维护时间:2024-01-01 02:00:00 至 2024-01-01 06:00:00</li>
<li>维护内容:数据库优化、服务器升级</li>
<li>影响范围:系统暂时不可用</li>
</ul>
<p>给您带来不便,敬请谅解!</p>
<p>技术支持团队</p>
""",
"status": "0",
"remark": "UAT测试-系统维护通知"
}
notice_response = await notice_api.create(notice_data)
assert notice_response.status_code in [200, 201], "创建系统通知失败"
notice_data_response = notice_response.json()
notice_id = notice_data_response.get("id")
if not notice_id:
all_notices = await notice_api.get_all()
notices = all_notices.json()
notice = next((n for n in notices if unique_id in n["noticeTitle"]), None)
notice_id = notice["id"] if notice else None
assert notice_id is not None, "获取通知ID失败"
test_data_manager.add_notice(notice_id)
# 步骤2: 验证通知创建成功
get_notice_response = await notice_api.get_by_id(notice_id)
assert get_notice_response.status_code == 200, "获取通知详情失败"
get_notice_data = get_notice_response.json()
assert unique_id in get_notice_data["noticeTitle"], "通知标题不匹配"
# 步骤3: 更新通知内容
update_notice_data = {
"noticeTitle": f"系统维护通知_已更新_{unique_id}",
"noticeContent": """
<h1>系统维护通知(更新版)</h1>
<p>尊敬的用户:</p>
<p>为提升系统性能,我们将于以下时间进行系统维护:</p>
<ul>
<li>维护时间:2024-01-01 02:00:00 至 2024-01-01 06:00:00</li>
<li>维护内容:数据库优化、服务器升级、安全补丁</li>
<li>影响范围:系统暂时不可用</li>
<li>更新说明:新增安全补丁更新</li>
</ul>
<p>给您带来不便,敬请谅解!</p>
<p>技术支持团队</p>
""",
"remark": "UAT测试-更新通知内容"
}
update_notice_response = await notice_api.update(notice_id, update_notice_data)
assert update_notice_response.status_code == 200, "更新通知失败"
# 步骤4: 验证通知更新成功
verify_notice_response = await notice_api.get_by_id(notice_id)
assert verify_notice_response.status_code == 200, "验证通知更新失败"
verify_notice_data = verify_notice_response.json()
assert "已更新" in verify_notice_data["noticeTitle"], "通知更新未生效"
assert "安全补丁" in verify_notice_data["noticeContent"], "通知内容更新未生效"
# 步骤5: 分页查询通知
notice_list_response = await notice_api.get_list(page=0, size=10)
assert notice_list_response.status_code == 200, "分页查询通知失败"
notice_list = notice_list_response.json()
assert "content" in notice_list, "通知列表缺少content字段"
assert "totalElements" in notice_list, "通知列表缺少totalElements字段"
# 步骤6: 删除通知
delete_notice_response = await notice_api.delete(notice_id)
assert delete_notice_response.status_code in [200, 204], "删除通知失败"
# 步骤7: 验证通知已删除
verify_delete_response = await notice_api.get_by_id(notice_id)
assert verify_delete_response.status_code in [404, 500], "删除的通知不应能查询到"
@pytest.mark.asyncio
async def test_uat_file_management(
self, authenticated_client, test_data_manager
):
"""
UAT-06: 文件管理验证
场景描述:
- 上传文件
- 查看文件列表
- 下载文件
- 删除文件
- 文件分类管理
"""
file_api = FileAPI(authenticated_client)
unique_id = f"uat_file_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 上传测试文件
test_file_content = f"""
UAT测试文件
文件ID: {unique_id}
创建时间: {time.strftime('%Y-%m-%d %H:%M:%S')}
文件内容: 这是用于UAT验收测试的文件内容
""".encode('utf-8')
upload_response = await file_api.upload_file(
f"uat_test_file_{unique_id}.txt",
test_file_content
)
assert upload_response.status_code == 200, "上传文件失败"
upload_data = upload_response.json()
file_id = upload_data.get("id") or upload_data.get("fileId")
assert file_id is not None, "获取文件ID失败"
test_data_manager.add_file(file_id)
# 步骤2: 验证文件上传成功
file_info_response = await file_api.get_file_info(file_id)
assert file_info_response.status_code == 200, "获取文件信息失败"
file_info = file_info_response.json()
assert f"uat_test_file_{unique_id}" in file_info.get("fileName", ""), "文件名不匹配"
# 步骤3: 查询文件列表
file_list_response = await file_api.get_file_list(page=0, size=10)
assert file_list_response.status_code == 200, "查询文件列表失败"
file_list = file_list_response.json()
assert "content" in file_list, "文件列表缺少content字段"
assert "totalElements" in file_list, "文件列表缺少totalElements字段"
# 步骤4: 下载文件
download_response = await file_api.download_file(file_id)
assert download_response.status_code == 200, "下载文件失败"
downloaded_content = download_response.content
assert downloaded_content == test_file_content, "下载的文件内容不匹配"
# 步骤5: 更新文件信息
update_file_data = {
"fileName": f"uat_test_file_{unique_id}_updated",
"fileType": "txt",
"remark": "UAT测试-更新文件信息"
}
update_file_response = await file_api.update_file(file_id, update_file_data)
assert update_file_response.status_code == 200, "更新文件信息失败"
# 步骤6: 删除文件
delete_file_response = await file_api.delete_file(file_id)
assert delete_file_response.status_code in [200, 204], "删除文件失败"
# 步骤7: 验证文件已删除
verify_delete_response = await file_api.get_file_info(file_id)
assert verify_delete_response.status_code in [404, 500], "删除的文件不应能查询到"
@pytest.mark.asyncio
async def test_uat_audit_log_verification(
self, authenticated_client, test_data_manager
):
"""
UAT-07: 审计日志验证
场景描述:
- 执行操作生成审计日志
- 查询操作日志
- 查询登录日志
- 查询异常日志
- 日志筛选和分页
"""
user_api = UserAPI(authenticated_client)
audit_api = AuditAPI(authenticated_client)
unique_id = f"uat_audit_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 创建测试用户以触发审计日志
audit_user_data = {
"username": f"audit_user_{unique_id}",
"password": "Audit123!@#",
"email": f"audit_{unique_id}@example.com",
"status": 1,
"remark": "UAT测试-审计日志用户"
}
audit_user_response = await user_api.create_user(audit_user_data)
assert audit_user_response.status_code == 201, "创建审计日志测试用户失败"
audit_user_id = audit_user_response.json()["id"]
test_data_manager.add_user(audit_user_id)
# 步骤2: 等待审计日志生成
await asyncio.sleep(1)
# 步骤3: 查询操作日志
operation_log_response = await audit_api.get_operation_logs(
page=0, size=10, operation=f"audit_user_{unique_id}"
)
assert operation_log_response.status_code == 200, "查询操作日志失败"
operation_logs = operation_log_response.json()
assert "content" in operation_logs, "操作日志缺少content字段"
assert "totalElements" in operation_logs, "操作日志缺少totalElements字段"
# 步骤4: 查询登录日志
login_log_response = await audit_api.get_login_logs(page=0, size=10)
assert login_log_response.status_code == 200, "查询登录日志失败"
login_logs = login_log_response.json()
assert "content" in login_logs, "登录日志缺少content字段"
assert "totalElements" in login_logs, "登录日志缺少totalElements字段"
# 步骤5: 查询异常日志
exception_log_response = await audit_api.get_exception_logs(page=0, size=10)
assert exception_log_response.status_code == 200, "查询异常日志失败"
exception_logs = exception_log_response.json()
assert "content" in exception_logs, "异常日志缺少content字段"
assert "totalElements" in exception_logs, "异常日志缺少totalElements字段"
# 步骤6: 按时间范围筛选日志
current_time = int(time.time() * 1000)
time_range_response = await audit_api.get_operation_logs(
page=0, size=10,
beginTime=str(current_time - 3600000),
endTime=str(current_time + 3600000)
)
assert time_range_response.status_code == 200, "按时间范围筛选日志失败"
# 步骤7: 按用户筛选日志
user_filter_response = await audit_api.get_operation_logs(
page=0, size=10,
userName=f"audit_user_{unique_id}"
)
assert user_filter_response.status_code == 200, "按用户筛选日志失败"
# 步骤8: 清理测试用户
await user_api.delete_user(audit_user_id)
test_data_manager._users.remove(audit_user_id)
@pytest.mark.asyncio
async def test_uat_performance_acceptance(
self, authenticated_client, test_data_manager
):
"""
UAT-08: 性能验收验证
场景描述:
- 测试接口响应时间
- 测试并发用户处理能力
- 测试大数据量查询性能
- 验证性能指标达标
"""
user_api = UserAPI(authenticated_client)
unique_id = f"uat_perf_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
performance_metrics = {}
# 步骤1: 创建测试用户
perf_user_data = {
"username": f"perf_user_{unique_id}",
"password": "Perf123!@#",
"email": f"perf_{unique_id}@example.com",
"status": 1
}
perf_user_response = await user_api.create_user(perf_user_data)
assert perf_user_response.status_code == 201, "创建性能测试用户失败"
perf_user_id = perf_user_response.json()["id"]
test_data_manager.add_user(perf_user_id)
# 步骤2: 测试单用户查询性能
start_time = time.time()
user_query_response = await user_api.get_user_by_id(perf_user_id)
query_duration = (time.time() - start_time) * 1000
assert user_query_response.status_code == 200, "查询用户失败"
assert query_duration < 500, f"单用户查询性能不达标: {query_duration}ms"
performance_metrics["single_user_query_ms"] = query_duration
# 步骤3: 创建多个用户用于并发测试
concurrent_user_ids = []
for i in range(10):
concurrent_user_data = {
"username": f"perf_concurrent_{unique_id}_{i}",
"password": "Perf123!@#",
"email": f"perf_concurrent_{unique_id}_{i}@example.com",
"status": 1
}
concurrent_user_response = await user_api.create_user(concurrent_user_data)
assert concurrent_user_response.status_code == 201, f"创建并发测试用户{i}失败"
concurrent_user_ids.append(concurrent_user_response.json()["id"])
test_data_manager.add_user(concurrent_user_ids[-1])
# 步骤4: 测试并发查询性能(5个并发)
start_time = time.time()
async def query_user(user_id):
response = await user_api.get_user_by_id(user_id)
return response.status_code == 200
tasks = [query_user(user_id) for user_id in concurrent_user_ids[:5]]
results = await asyncio.gather(*tasks)
concurrent_query_duration = (time.time() - start_time) * 1000
assert all(results), "并发查询存在失败"
assert concurrent_query_duration < 2000, f"并发查询性能不达标: {concurrent_query_duration}ms"
performance_metrics["concurrent_query_5_users_ms"] = concurrent_query_duration
# 步骤5: 测试分页查询性能
pagination_start = time.time()
pagination_response = await user_api.get_users_by_page(page=0, size=100)
pagination_duration = (time.time() - pagination_start) * 1000
assert pagination_response.status_code == 200, "分页查询失败"
assert pagination_duration < 1000, f"分页查询性能不达标: {pagination_duration}ms"
performance_metrics["pagination_query_100_ms"] = pagination_duration
# 步骤6: 验证性能指标
assert performance_metrics["single_user_query_ms"] < 500, "单用户查询性能不达标"
assert performance_metrics["concurrent_query_5_users_ms"] < 2000, "并发查询性能不达标"
assert performance_metrics["pagination_query_100_ms"] < 1000, "分页查询性能不达标"
# 步骤7: 清理测试用户
for user_id in concurrent_user_ids:
await user_api.delete_user(user_id)
test_data_manager._users.remove(user_id)
await user_api.delete_user(perf_user_id)
test_data_manager._users.remove(perf_user_id)
@pytest.mark.asyncio
async def test_uat_security_acceptance(
self, authenticated_client, test_data_manager
):
"""
UAT-09: 安全验收验证
场景描述:
- 测试SQL注入防护
- 测试XSS攻击防护
- 测试认证授权
- 测试密码策略
- 测试敏感信息保护
"""
user_api = UserAPI(authenticated_client)
unique_id = f"uat_security_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# 步骤1: 测试SQL注入防护
sql_injection_username = f"test' OR '1'='1' -- {unique_id}"
sql_injection_data = {
"username": sql_injection_username,
"password": "Test123!@#",
"email": f"sql_injection_{unique_id}@example.com",
"status": 1
}
sql_injection_response = await user_api.create_user(sql_injection_data)
# 应该成功创建(转义处理),但不应被SQL注入影响
assert sql_injection_response.status_code in [201, 400, 422], "SQL注入尝试应被拦截或正确处理"
# 步骤2: 测试XSS攻击防护
xss_username = f"<script>alert('XSS')</script>_{unique_id}"
xss_data = {
"username": xss_username,
"password": "Test123!@#",
"email": f"xss_{unique_id}@example.com",
"status": 1
}
xss_response = await user_api.create_user(xss_data)
# 应该被正确处理(转义或拒绝)
assert xss_response.status_code in [201, 400, 422], "XSS攻击应被拦截或正确处理"
# 步骤3: 测试弱密码检测
weak_password_data = {
"username": f"weak_password_{unique_id}",
"password": "123456",
"email": f"weak_{unique_id}@example.com",
"status": 1
}
weak_password_response = await user_api.create_user(weak_password_data)
# 应该被拒绝
assert weak_password_response.status_code in [400, 422], "弱密码应被拒绝"
# 步骤4: 测试重复用户名检测
duplicate_username = f"duplicate_{unique_id}"
duplicate_data1 = {
"username": duplicate_username,
"password": "Test123!@#",
"email": f"duplicate1_{unique_id}@example.com",
"status": 1
}
duplicate_data2 = {
"username": duplicate_username,
"password": "Test123!@#",
"email": f"duplicate2_{unique_id}@example.com",
"status": 1
}
duplicate_response1 = await user_api.create_user(duplicate_data1)
assert duplicate_response1.status_code == 201, "创建第一个重复用户名用户失败"
duplicate_response2 = await user_api.create_user(duplicate_data2)
assert duplicate_response2.status_code in [400, 409, 422], "重复用户名应被拒绝"
# 步骤5: 测试无效邮箱格式
invalid_email_data = {
"username": f"invalid_email_{unique_id}",
"password": "Test123!@#",
"email": "invalid-email-format",
"status": 1
}
invalid_email_response = await user_api.create_user(invalid_email_data)
assert invalid_email_response.status_code in [400, 422], "无效邮箱格式应被拒绝"
# 步骤6: 测试空用户名
empty_username_data = {
"username": "",
"password": "Test123!@#",
"email": f"empty_{unique_id}@example.com",
"status": 1
}
empty_username_response = await user_api.create_user(empty_username_data)
assert empty_username_response.status_code in [400, 422], "空用户名应被拒绝"
# 步骤7: 测试空密码
empty_password_data = {
"username": f"empty_password_{unique_id}",
"password": "",
"email": f"empty_password_{unique_id}@example.com",
"status": 1
}
empty_password_response = await user_api.create_user(empty_password_data)
assert empty_password_response.status_code in [400, 422], "空密码应被拒绝"
# 步骤8: 测试超长输入
long_username = "a" * 200
long_data = {
"username": long_username,
"password": "Test123!@#",
"email": f"long_{unique_id}@example.com",
"status": 1
}
long_response = await user_api.create_user(long_data)
assert long_response.status_code in [400, 422], "超长输入应被拒绝"
# 步骤9: 测试特殊字符处理
special_char_data = {
"username": f"special!@#$%^&*()_{unique_id}",
"password": "Test123!@#",
"email": f"special_{unique_id}@example.com",
"status": 1
}
special_char_response = await user_api.create_user(special_char_data)
# 特殊字符应被正确处理
assert special_char_response.status_code in [201, 400, 422], "特殊字符应被正确处理"
@pytest.mark.asyncio
async def test_uat_business_workflow(
self, authenticated_client, test_data_manager
):
"""
UAT-10: 完整业务流程验证
场景描述:
- 从用户创建到权限分配的完整流程
- 从角色配置到菜单授权的完整流程
- 从数据字典维护到配置管理的完整流程
- 验证端到端业务流程
"""
user_api = UserAPI(authenticated_client)
role_api = RoleAPI(authenticated_client)
menu_api = MenuAPI(authenticated_client)
dict_api = DictAPI(authenticated_client)
config_api = ConfigAPI(authenticated_client)
unique_id = f"uat_workflow_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
# ==================== 第一部分:用户与角色 ====================
# 1.1 创建部门经理角色
manager_role_data = {
"roleName": f"Workflow_Manager_Role_{unique_id}",
"roleKey": f"workflow_manager_role_{unique_id}",
"roleSort": 5,
"status": 1,
"remark": "UAT测试-业务流程-部门经理"
}
manager_role_response = await role_api.create_role(manager_role_data)
assert manager_role_response.status_code == 201, "创建部门经理角色失败"
manager_role_id = manager_role_response.json()["id"]
test_data_manager.add_role(manager_role_id)
# 1.2 创建普通员工角色
employee_role_data = {
"roleName": f"Workflow_Employee_Role_{unique_id}",
"roleKey": f"workflow_employee_role_{unique_id}",
"roleSort": 10,
"status": 1,
"remark": "UAT测试-业务流程-普通员工"
}
employee_role_response = await role_api.create_role(employee_role_data)
assert employee_role_response.status_code == 201, "创建普通员工角色失败"
employee_role_id = employee_role_response.json()["id"]
test_data_manager.add_role(employee_role_id)
# 1.3 创建系统管理员角色
admin_role_data = {
"roleName": f"Workflow_Admin_Role_{unique_id}",
"roleKey": f"workflow_admin_role_{unique_id}",
"roleSort": 1,
"status": 1,
"remark": "UAT测试-业务流程-系统管理员"
}
admin_role_response = await role_api.create_role(admin_role_data)
assert admin_role_response.status_code == 201, "创建系统管理员角色失败"
admin_role_id = admin_role_response.json()["id"]
test_data_manager.add_role(admin_role_id)
# ==================== 第二部分:菜单与权限 ====================
# 2.1 创建系统管理主菜单
system_menu_data = {
"parentId": 0,
"menuName": f"系统管理_{unique_id}",
"menuType": "M",
"orderNum": 1,
"component": "Layout",
"perms": f"system:workflow:{unique_id}",
"status": 1,
"icon": "system"
}
system_menu_response = await menu_api.create_menu(system_menu_data)
assert system_menu_response.status_code == 201, "创建系统管理菜单失败"
system_menu_id = system_menu_response.json()["id"]
test_data_manager.add_menu(system_menu_id)
# 2.2 创建用户管理子菜单
user_menu_data = {
"parentId": system_menu_id,
"menuName": "用户管理",
"menuType": "C",
"orderNum": 1,
"component": "UserManagement",
"perms": f"user:workflow:{unique_id}",
"status": 1
}
user_menu_response = await menu_api.create_menu(user_menu_data)
assert user_menu_response.status_code == 201, "创建用户管理菜单失败"
user_menu_id = user_menu_response.json()["id"]
test_data_manager.add_menu(user_menu_id)
# 2.3 创建角色管理子菜单
role_menu_data = {
"parentId": system_menu_id,
"menuName": "角色管理",
"menuType": "C",
"orderNum": 2,
"component": "RoleManagement",
"perms": f"role:workflow:{unique_id}",
"status": 1
}
role_menu_response = await menu_api.create_menu(role_menu_data)
assert role_menu_response.status_code == 201, "创建角色管理菜单失败"
role_menu_id = role_menu_response.json()["id"]
test_data_manager.add_menu(role_menu_id)
# 2.4 创建权限分配
admin_permission_data = {"menuIds": [system_menu_id, user_menu_id, role_menu_id]}
admin_permission_response = await role_api.assign_permissions(admin_role_id, admin_permission_data)
assert admin_permission_response.status_code == 200, "为管理员分配权限失败"
manager_permission_data = {"menuIds": [user_menu_id]}
manager_permission_response = await role_api.assign_permissions(manager_role_id, manager_permission_data)
assert manager_permission_response.status_code == 200, "为经理分配权限失败"
employee_permission_data = {"menuIds": []}
employee_permission_response = await role_api.assign_permissions(employee_role_id, employee_permission_data)
assert employee_permission_response.status_code == 200, "为员工分配权限失败"
# ==================== 第三部分:数据字典 ====================
# 3.1 创建用户状态字典
status_type_data = {
"type": f"WORKFLOW_STATUS_{unique_id}",
"name": "用户状态",
"remark": "UAT测试-业务流程-用户状态",
"sort": 1
}
status_type_response = await dict_api.create_type(status_type_data)
assert status_type_response.status_code == 201, "创建用户状态字典类型失败"
status_type_id = status_type_response.json()["id"]
test_data_manager.add_dict_type(status_type_id)
# 3.2 添加状态数据
enabled_status_data = {
"type": f"WORKFLOW_STATUS_{unique_id}",
"code": "ENABLED",
"name": "启用",
"value": "1",
"remark": "用户已启用",
"sort": 1
}
enabled_status_response = await dict_api.create(enabled_status_data)
assert enabled_status_response.status_code == 201, "添加启用状态失败"
enabled_status_id = enabled_status_response.json()["id"]
test_data_manager.add_dict(enabled_status_id)
disabled_status_data = {
"type": f"WORKFLOW_STATUS_{unique_id}",
"code": "DISABLED",
"name": "禁用",
"value": "0",
"remark": "用户已禁用",
"sort": 2
}
disabled_status_response = await dict_api.create(disabled_status_data)
assert disabled_status_response.status_code == 201, "添加禁用状态失败"
disabled_status_id = disabled_status_response.json()["id"]
test_data_manager.add_dict(disabled_status_id)
# ==================== 第四部分:系统配置 ====================
# 4.1 创建系统配置
system_config_data = {
"configKey": f"workflow_config_{unique_id}",
"configName": "UAT业务流程配置",
"configType": "Y",
"configValue": '{"maxUsers":1000,"enableAudit":true}',
"remark": "UAT测试-业务流程-系统配置"
}
system_config_response = await config_api.create_config(system_config_data)
assert system_config_response.status_code == 201, "创建系统配置失败"
system_config_id = system_config_response.json()["id"]
test_data_manager.add_config(system_config_id)
# ==================== 第五部分:用户创建与管理 ====================
# 5.1 创建测试用户
test_user_data = {
"username": f"workflow_user_{unique_id}",
"password": "Workflow123!@#",
"email": f"workflow_{unique_id}@company.com",
"roleId": employee_role_id,
"status": 1,
"remark": "UAT测试-业务流程-测试用户"
}
test_user_response = await user_api.create_user(test_user_data)
assert test_user_response.status_code == 201, "创建测试用户失败"
test_user_id = test_user_response.json()["id"]
test_data_manager.add_user(test_user_id)
# 5.2 验证用户创建成功
user_detail_response = await user_api.get_user_by_id(test_user_id)
assert user_detail_response.status_code == 200, "验证用户详情失败"
user_detail = user_detail_response.json()
assert user_detail["username"] == f"workflow_user_{unique_id}", "用户详情不匹配"
# 5.3 更新用户角色(晋升)
update_user_role_data = {"roleId": manager_role_id}
update_user_role_response = await user_api.update_user(test_user_id, update_user_role_data)
assert update_user_role_response.status_code == 200, "更新用户角色失败"
# 5.4 验证角色更新
verify_role_response = await user_api.get_user_by_id(test_user_id)
assert verify_role_response.status_code == 200, "验证角色更新失败"
verify_role_detail = verify_role_response.json()
assert verify_role_detail["roleId"] == manager_role_id, "角色更新未生效"
# 5.5 更新用户个人信息
update_profile_data = {
"nickName": f"测试用户_{unique_id}",
"phone": f"1380013800{unique_id[-4:]}",
"remark": "UAT测试-业务流程-更新个人信息"
}
update_profile_response = await user_api.update_user_profile(update_profile_data)
assert update_profile_response.status_code == 200, "更新个人信息失败"
# ==================== 第六部分:权限验证 ====================
# 6.1 验证管理员权限
admin_menus_response = await menu_api.get_user_menus_by_role(admin_role_id)
assert admin_menus_response.status_code == 200, "获取管理员菜单失败"
admin_menus = admin_menus_response.json()
assert len(admin_menus) >= 3, "管理员应能访问至少3个菜单"
# 6.2 验证经理权限
manager_menus_response = await menu_api.get_user_menus_by_role(manager_role_id)
assert manager_menus_response.status_code == 200, "获取经理菜单失败"
manager_menus = manager_menus_response.json()
assert len(manager_menus) == 1, "经理应只能访问1个菜单"
assert manager_menus[0]["id"] == user_menu_id, "经理菜单权限不正确"
# 6.3 验证员工权限
employee_menus_response = await menu_api.get_user_menus_by_role(employee_role_id)
assert employee_menus_response.status_code == 200, "获取员工菜单失败"
employee_menus = employee_menus_response.json()
assert len(employee_menus) == 0, "员工应无菜单权限"
# ==================== 第七部分:清理 ====================
# 7.1 删除测试用户
await user_api.delete_user(test_user_id)
test_data_manager._users.remove(test_user_id)
# 7.2 清理权限分配
await role_api.assign_permissions(admin_role_id, {"menuIds": []})
await role_api.assign_permissions(manager_role_id, {"menuIds": []})
await role_api.assign_permissions(employee_role_id, {"menuIds": []})
# 7.3 删除菜单
await menu_api.delete_menu(role_menu_id)
test_data_manager._menus.remove(role_menu_id)
await menu_api.delete_menu(user_menu_id)
test_data_manager._menus.remove(user_menu_id)
await menu_api.delete_menu(system_menu_id)
test_data_manager._menus.remove(system_menu_id)
# 7.4 删除角色
await role_api.delete_role(admin_role_id)
test_data_manager._roles.remove(admin_role_id)
await role_api.delete_role(manager_role_id)
test_data_manager._roles.remove(manager_role_id)
await role_api.delete_role(employee_role_id)
test_data_manager._roles.remove(employee_role_id)
# 7.5 删除字典数据
await dict_api.delete_dict(disabled_status_id)
test_data_manager._dicts.remove(disabled_status_id)
await dict_api.delete_dict(enabled_status_id)
test_data_manager._dicts.remove(enabled_status_id)
await dict_api.delete_type(status_type_id)
test_data_manager._dict_types.remove(status_type_id)
# 7.6 删除系统配置
await config_api.delete_config(system_config_id)
test_data_manager._configs.remove(system_config_id)