Files

751 lines
27 KiB
Python

"""
用户生命周期UAT测试 - 模拟真实业务场景
"""
import pytest
import time
from playwright.async_api import async_playwright, Page
from httpx import AsyncClient
from config.settings import settings
@pytest.mark.uat
@pytest.mark.user_lifecycle
class TestUserLifecycleUAT:
"""用户生命周期UAT测试"""
@pytest.fixture
async def browser(self):
"""浏览器fixture"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
yield browser
await browser.close()
@pytest.fixture
async def context(self, browser):
"""浏览器上下文fixture"""
context = await browser.new_context()
yield context
await context.close()
@pytest.fixture
async def page(self, context):
"""页面fixture"""
page = await context.new_page()
page.set_default_timeout(30000)
yield page
await page.close()
@pytest.fixture
async def authenticated_client(self):
"""已认证的HTTP客户端"""
async with AsyncClient(base_url=settings.API_BASE_URL) as client:
response = await client.post(
"/api/auth/login",
json={
"username": settings.TEST_USERNAME,
"password": settings.TEST_PASSWORD
}
)
assert response.status_code == 200
token = response.json().get("token")
client.headers.update({"Authorization": f"Bearer {token}"})
yield client
@pytest.mark.asyncio
async def test_uat_user_registration_and_login(self, page, authenticated_client):
"""UAT: 用户注册和登录流程"""
timestamp = int(time.time() * 1000)
username = f"uat_user_{timestamp}"
email = f"uat_{timestamp}@example.com"
password = "Test123!@#"
# 步骤1: 通过API创建用户
response = await authenticated_client.post(
"/api/users",
json={
"username": username,
"password": password,
"email": email,
"phone": "13800138000",
"status": 1
}
)
assert response.status_code == 201, f"创建用户失败: {response.text}"
user_id = response.json()["id"]
try:
# 步骤2: 通过前端登录
await page.goto("http://localhost:3002/login")
await page.wait_for_load_state("networkidle")
await page.fill('input[placeholder="请输入用户名"]', username)
await page.fill('input[placeholder="请输入密码"]', password)
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.wait_for_load_state("networkidle")
# 步骤3: 验证登录成功
title = await page.title()
assert "首页" in title or "Dashboard" in title, "登录后未跳转到首页"
# 步骤4: 验证用户信息显示
user_info = await page.query_selector('.user-info')
assert user_info is not None, "用户信息元素未找到"
finally:
# 清理
await authenticated_client.delete(f"/api/users/{user_id}")
@pytest.mark.asyncio
async def test_uat_user_profile_update(self, page, authenticated_client):
"""UAT: 用户资料更新流程"""
timestamp = int(time.time() * 1000)
username = f"uat_profile_{timestamp}"
email = f"uat_profile_{timestamp}@example.com"
# 步骤1: 创建测试用户
response = await authenticated_client.post(
"/api/users",
json={
"username": username,
"password": "Test123!@#",
"email": email,
"phone": "13800138000",
"status": 1
}
)
assert response.status_code == 201
user_id = response.json()["id"]
try:
# 步骤2: 登录
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', username)
await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
# 步骤3: 访问用户资料页面
await page.click('text=用户管理')
await page.wait_for_url("**/users")
# 步骤4: 编辑用户
await page.click('text=编辑')
await page.wait_for_load_state("networkidle")
# 步骤5: 更新资料
await page.fill('input[placeholder=""]', '测试用户昵称')
await page.fill('input[placeholder=""]', '13900139000')
await page.click('button:has-text("确定")')
await page.wait_for_load_state("networkidle")
# 步骤6: 验证更新
page_content = await page.content()
assert "测试用户昵称" in page_content
finally:
await authenticated_client.delete(f"/api/users/{user_id}")
@pytest.mark.asyncio
async def test_uat_user_status_change(self, page, authenticated_client):
"""UAT: 用户状态变更流程"""
timestamp = int(time.time() * 1000)
username = f"uat_status_{timestamp}"
# 创建用户
response = await authenticated_client.post(
"/api/users",
json={
"username": username,
"password": "Test123!@#",
"email": f"uat_status_{timestamp}@example.com",
"status": 1
}
)
assert response.status_code == 201
user_id = response.json()["id"]
try:
# 登录并禁用用户
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', username)
await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
# 尝试禁用用户
await page.click('text=用户管理')
await page.wait_for_url("**/users")
# 禁用用户
await page.click('button:has-text("禁用")')
await page.click('button:has-text("确定")')
await page.wait_for_load_state("networkidle")
# 验证状态变更
page_content = await page.content()
assert "禁用" in page_content
finally:
await authenticated_client.delete(f"/api/users/{user_id}")
@pytest.mark.asyncio
async def test_uat_user_delete(self, page, authenticated_client):
"""UAT: 用户删除流程"""
timestamp = int(time.time() * 1000)
username = f"uat_delete_{timestamp}"
# 创建用户
response = await authenticated_client.post(
"/api/users",
json={
"username": username,
"password": "Test123!@#",
"email": f"uat_delete_{timestamp}@example.com",
"status": 1
}
)
assert response.status_code == 201
user_id = response.json()["id"]
# 登录并删除用户
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', username)
await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=用户管理')
await page.wait_for_url("**/users")
await page.click('button:has-text("删除")')
await page.click('button:has-text("确定")')
await page.wait_for_load_state("networkidle")
# 验证删除
page_content = await page.content()
assert username not in page_content
@pytest.mark.uat
@pytest.mark.role_workflow
class TestRoleWorkflowUAT:
"""角色工作流UAT测试"""
@pytest.fixture
async def browser(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
yield browser
await browser.close()
@pytest.fixture
async def context(self, browser):
context = await browser.new_context()
yield context
await context.close()
@pytest.fixture
async def page(self, context):
page = await context.new_page()
page.set_default_timeout(30000)
yield page
await page.close()
@pytest.fixture
async def authenticated_client(self):
async with AsyncClient(base_url=settings.API_BASE_URL) as client:
response = await client.post(
"/api/auth/login",
json={
"username": settings.TEST_USERNAME,
"password": settings.TEST_PASSWORD
}
)
assert response.status_code == 200
token = response.json().get("token")
client.headers.update({"Authorization": f"Bearer {token}"})
yield client
@pytest.mark.asyncio
async def test_uat_role_assignment(self, page, authenticated_client):
"""UAT: 角色分配流程"""
timestamp = int(time.time() * 1000)
username = f"uat_role_user_{timestamp}"
role_name = f"UAT_Role_{timestamp}"
# 创建角色
role_response = await authenticated_client.post(
"/api/roles",
json={
"roleName": role_name,
"roleKey": f"uat_role_{timestamp}",
"roleSort": 1,
"status": 1
}
)
assert role_response.status_code == 201
role_id = role_response.json()["id"]
try:
# 创建用户
user_response = await authenticated_client.post(
"/api/users",
json={
"username": username,
"password": "Test123!@#",
"email": f"uat_role_user_{timestamp}@example.com",
"status": 1
}
)
assert user_response.status_code == 201
user_id = user_response.json()["id"]
# 登录并分配角色
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', username)
await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=用户管理')
await page.wait_for_url("**/users")
# 分配角色
await page.click('text=分配角色')
await page.wait_for_load_state("networkidle")
# 选择角色
await page.click(f'text={role_name}')
await page.click('button:has-text("确定")')
await page.wait_for_load_state("networkidle")
# 验证角色分配
user_info = await authenticated_client.get(f"/api/users/{user_id}")
assert user_info.status_code == 200
user_data = user_info.json()
assert user_data["roleId"] == role_id
finally:
await authenticated_client.delete(f"/api/users/{user_id}")
await authenticated_client.delete(f"/api/roles/{role_id}")
@pytest.mark.asyncio
async def test_uat_role_permission_management(self, page, authenticated_client):
"""UAT: 角色权限管理流程"""
timestamp = int(time.time() * 1000)
role_name = f"UAT_Permission_Role_{timestamp}"
# 创建角色
role_response = await authenticated_client.post(
"/api/roles",
json={
"roleName": role_name,
"roleKey": f"uat_perm_role_{timestamp}",
"roleSort": 1,
"status": 1
}
)
assert role_response.status_code == 201
role_id = role_response.json()["id"]
try:
# 登录并访问角色管理
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=角色管理')
await page.wait_for_url("**/roles")
# 编辑角色权限
await page.click('text=编辑')
await page.wait_for_load_state("networkidle")
# 更新角色信息
await page.fill('input[placeholder=""]', f"{role_name}_updated")
await page.click('button:has-text("确定")')
await page.wait_for_load_state("networkidle")
# 验证更新
roles_response = await authenticated_client.get("/api/roles")
roles = roles_response.json()
role_exists = any(r['roleName'] == f"{role_name}_updated" for r in roles)
assert role_exists
finally:
await authenticated_client.delete(f"/api/roles/{role_id}")
@pytest.mark.uat
@pytest.mark.config_workflow
class TestConfigWorkflowUAT:
"""配置工作流UAT测试"""
@pytest.fixture
async def browser(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
yield browser
await browser.close()
@pytest.fixture
async def context(self, browser):
context = await browser.new_context()
yield context
await context.close()
@pytest.fixture
async def page(self, context):
page = await context.new_page()
page.set_default_timeout(30000)
yield page
await page.close()
@pytest.fixture
async def authenticated_client(self):
async with AsyncClient(base_url=settings.API_BASE_URL) as client:
response = await client.post(
"/api/auth/login",
json={
"username": settings.TEST_USERNAME,
"password": settings.TEST_PASSWORD
}
)
assert response.status_code == 200
token = response.json().get("token")
client.headers.update({"Authorization": f"Bearer {token}"})
yield client
@pytest.mark.asyncio
async def test_uat_system_config_update(self, page, authenticated_client):
"""UAT: 系统配置更新流程"""
timestamp = int(time.time() * 1000)
# 登录并访问系统配置
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=系统配置')
await page.wait_for_url("**/config")
await page.wait_for_load_state("networkidle")
# 编辑配置
await page.click('text=编辑')
await page.wait_for_load_state("networkidle")
# 更新配置
await page.fill('input[placeholder=""]', f"Test_Config_{timestamp}")
await page.fill('textarea[placeholder=""]', '测试配置内容')
await page.click('button:has-text("确定")')
await page.wait_for_load_state("networkidle")
# 验证更新
config_response = await authenticated_client.get("/api/config")
assert config_response.status_code == 200
@pytest.mark.uat
@pytest.mark.data_dict_workflow
class TestDataDictWorkflowUAT:
"""数据字典工作流UAT测试"""
@pytest.fixture
async def browser(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
yield browser
await browser.close()
@pytest.fixture
async def context(self, browser):
context = await browser.new_context()
yield context
await context.close()
@pytest.fixture
async def page(self, context):
page = await context.new_page()
page.set_default_timeout(30000)
yield page
await page.close()
@pytest.fixture
async def authenticated_client(self):
async with AsyncClient(base_url=settings.API_BASE_URL) as client:
response = await client.post(
"/api/auth/login",
json={
"username": settings.TEST_USERNAME,
"password": settings.TEST_PASSWORD
}
)
assert response.status_code == 200
token = response.json().get("token")
client.headers.update({"Authorization": f"Bearer {token}"})
yield client
@pytest.mark.asyncio
async def test_uat_dict_type_management(self, page, authenticated_client):
"""UAT: 字典类型管理流程"""
timestamp = int(time.time() * 1000)
dict_type = f"UAT_DICT_{timestamp}"
# 登录并访问字典管理
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=字典管理')
await page.wait_for_url("**/dicts")
await page.wait_for_load_state("networkidle")
# 创建字典类型
await page.click('text=新增字典')
await page.wait_for_load_state("networkidle")
await page.fill('input[placeholder=""]', dict_type)
await page.fill('input[placeholder=""]', f"uat_dict_{timestamp}")
await page.fill('textarea[placeholder=""]', '测试字典类型')
await page.click('button:has-text("确定")')
await page.wait_for_load_state("networkidle")
# 验证创建
dicts_response = await authenticated_client.get("/api/dict/types")
assert dicts_response.status_code == 200
dicts = dicts_response.json()
dict_exists = any(d['type'] == dict_type for d in dicts)
assert dict_exists
@pytest.mark.asyncio
async def test_uat_dict_data_management(self, page, authenticated_client):
"""UAT: 字典数据管理流程"""
timestamp = int(time.time() * 1000)
# 登录并访问字典管理
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=字典管理')
await page.wait_for_url("**/dicts")
await page.wait_for_load_state("networkidle")
# 查看字典数据
await page.click('text=查看')
await page.wait_for_load_state("networkidle")
# 验证字典数据列表
page_content = await page.content()
assert "字典数据" in page_content or "code" in page_content.lower()
@pytest.mark.uat
@pytest.mark.audit_workflow
class TestAuditWorkflowUAT:
"""审计工作流UAT测试"""
@pytest.fixture
async def browser(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
yield browser
await browser.close()
@pytest.fixture
async def context(self, browser):
context = await browser.new_context()
yield context
await context.close()
@pytest.fixture
async def page(self, context):
page = await context.new_page()
page.set_default_timeout(30000)
yield page
await page.close()
@pytest.fixture
async def authenticated_client(self):
async with AsyncClient(base_url=settings.API_BASE_URL) as client:
response = await client.post(
"/api/auth/login",
json={
"username": settings.TEST_USERNAME,
"password": settings.TEST_PASSWORD
}
)
assert response.status_code == 200
token = response.json().get("token")
client.headers.update({"Authorization": f"Bearer {token}"})
yield client
@pytest.mark.asyncio
async def test_uat_operation_log_audit(self, page, authenticated_client):
"""UAT: 操作日志审计流程"""
timestamp = int(time.time() * 1000)
# 登录并访问操作日志
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=操作日志')
await page.wait_for_url("**/operation-logs")
await page.wait_for_load_state("networkidle")
# 验证操作日志列表
await page.wait_for_selector('.el-card', timeout=10000)
# 通过API验证
logs_response = await authenticated_client.get("/api/audit/operation-logs")
assert logs_response.status_code == 200
logs = logs_response.json()
assert len(logs) > 0, "操作日志为空"
@pytest.mark.asyncio
async def test_uat_login_log_audit(self, page, authenticated_client):
"""UAT: 登录日志审计流程"""
# 登录并访问登录日志
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
await page.click('text=登录日志')
await page.wait_for_url("**/login-logs")
await page.wait_for_load_state("networkidle")
# 验证登录日志列表
await page.wait_for_selector('.el-card', timeout=10000)
# 通过API验证
login_logs_response = await authenticated_client.get("/api/audit/login-logs")
assert login_logs_response.status_code == 200
login_logs = login_logs_response.json()
assert len(login_logs) > 0, "登录日志为空"
@pytest.mark.uat
@pytest.mark.comprehensive_workflow
class TestComprehensiveWorkflowUAT:
"""综合业务流程UAT测试"""
@pytest.fixture
async def browser(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
yield browser
await browser.close()
@pytest.fixture
async def context(self, browser):
context = await browser.new_context()
yield context
await context.close()
@pytest.fixture
async def page(self, context):
page = await context.new_page()
page.set_default_timeout(30000)
yield page
await page.close()
@pytest.fixture
async def authenticated_client(self):
async with AsyncClient(base_url=settings.API_BASE_URL) as client:
response = await client.post(
"/api/auth/login",
json={
"username": settings.TEST_USERNAME,
"password": settings.TEST_PASSWORD
}
)
assert response.status_code == 200
token = response.json().get("token")
client.headers.update({"Authorization": f"Bearer {token}"})
yield client
@pytest.mark.asyncio
async def test_uat_complete_business_workflow(self, page, authenticated_client):
"""UAT: 完整业务流程测试"""
timestamp = int(time.time() * 1000)
# 步骤1: 用户注册
username = f"uat_complete_{timestamp}"
response = await authenticated_client.post(
"/api/users",
json={
"username": username,
"password": "Test123!@#",
"email": f"uat_complete_{timestamp}@example.com",
"phone": "13800138000",
"status": 1
}
)
assert response.status_code == 201
user_id = response.json()["id"]
try:
# 步骤2: 用户登录
await page.goto("http://localhost:3002/login")
await page.fill('input[placeholder="请输入用户名"]', username)
await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
await page.click('button[type="submit"]')
await page.wait_for_url("**/")
# 步骤3: 浏览用户管理
await page.click('text=用户管理')
await page.wait_for_url("**/users")
# 步骤4: 浏览角色管理
await page.click('text=角色管理')
await page.wait_for_url("**/roles")
# 步骤5: 浏览系统配置
await page.click('text=系统配置')
await page.wait_for_url("**/config")
# 步骤6: 浏览字典管理
await page.click('text=字典管理')
await page.wait_for_url("**/dicts")
# 步骤7: 浏览通知管理
await page.click('text=通知管理')
await page.wait_for_url("**/notices")
# 步骤8: 浏览文件管理
await page.click('text=文件管理')
await page.wait_for_url("**/files")
# 步骤9: 浏览审计日志
await page.click('text=操作日志')
await page.wait_for_url("**/operation-logs")
# 步骤10: 登出
await page.click('text=退出登录')
await page.wait_for_url("**/login")
finally:
await authenticated_client.delete(f"/api/users/{user_id}")