287 lines
7.5 KiB
Python
287 lines
7.5 KiB
Python
"""
|
|
测试配置和Fixtures
|
|
"""
|
|
import pytest
|
|
from httpx import AsyncClient, ASGITransport
|
|
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
|
from sqlalchemy.pool import StaticPool
|
|
from datetime import datetime
|
|
from typing import AsyncGenerator
|
|
|
|
from app.main import app
|
|
from app.db.base import Base
|
|
from app.models.user import User, Role, UserRole, Permission
|
|
from app.models.device_type import DeviceType, DeviceTypeField
|
|
from app.core.security import get_password_hash, security_manager
|
|
|
|
|
|
# 创建测试数据库引擎
|
|
test_engine = create_async_engine(
|
|
"sqlite+aiosqlite:///:memory:",
|
|
connect_args={"check_same_thread": False},
|
|
poolclass=StaticPool,
|
|
)
|
|
|
|
# 创建测试会话工厂
|
|
TestSessionLocal = async_sessionmaker(
|
|
test_engine,
|
|
class_=AsyncSession,
|
|
expire_on_commit=False,
|
|
autocommit=False,
|
|
autoflush=False,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
async def db_session():
|
|
"""创建测试数据库会话"""
|
|
async with test_engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.create_all)
|
|
|
|
async with TestSessionLocal() as session:
|
|
yield session
|
|
await session.rollback()
|
|
|
|
async with test_engine.begin() as conn:
|
|
await conn.run_sync(Base.metadata.drop_all)
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
async def client(db_session):
|
|
"""创建测试客户端"""
|
|
from app.core.deps import get_db
|
|
|
|
async def override_get_db():
|
|
yield db_session
|
|
|
|
app.dependency_overrides[get_db] = override_get_db
|
|
|
|
async with AsyncClient(
|
|
transport=ASGITransport(app=app),
|
|
base_url="http://test"
|
|
) as ac:
|
|
yield ac
|
|
|
|
app.dependency_overrides.clear()
|
|
|
|
|
|
# ===== 用户相关Fixtures =====
|
|
|
|
@pytest.fixture
|
|
async def test_password() -> str:
|
|
"""测试密码"""
|
|
return "Test123456"
|
|
|
|
|
|
@pytest.fixture
|
|
async def test_user(db_session: AsyncSession, test_password: str) -> User:
|
|
"""创建测试用户"""
|
|
user = User(
|
|
username="testuser",
|
|
password_hash=get_password_hash(test_password),
|
|
real_name="测试用户",
|
|
email="test@example.com",
|
|
phone="13800138000",
|
|
status="active",
|
|
is_admin=False
|
|
)
|
|
db_session.add(user)
|
|
await db_session.flush()
|
|
await db_session.refresh(user)
|
|
return user
|
|
|
|
|
|
@pytest.fixture
|
|
async def test_admin(db_session: AsyncSession, test_password: str) -> User:
|
|
"""创建测试管理员"""
|
|
admin = User(
|
|
username="admin",
|
|
password_hash=get_password_hash(test_password),
|
|
real_name="系统管理员",
|
|
email="admin@example.com",
|
|
status="active",
|
|
is_admin=True
|
|
)
|
|
db_session.add(admin)
|
|
await db_session.flush()
|
|
await db_session.refresh(admin)
|
|
return admin
|
|
|
|
|
|
@pytest.fixture
|
|
async def test_role(db_session: AsyncSession) -> Role:
|
|
"""创建测试角色"""
|
|
role = Role(
|
|
role_name="测试角色",
|
|
role_code="TEST_ROLE",
|
|
description="用于测试的角色",
|
|
status="active",
|
|
sort_order=1
|
|
)
|
|
db_session.add(role)
|
|
await db_session.flush()
|
|
await db_session.refresh(role)
|
|
return role
|
|
|
|
|
|
@pytest.fixture
|
|
async def auth_headers(client: AsyncClient, test_user: User, test_password: str) -> dict:
|
|
"""获取认证头"""
|
|
# 登录获取token
|
|
response = await client.post(
|
|
"/api/v1/auth/login",
|
|
json={
|
|
"username": test_user.username,
|
|
"password": test_password,
|
|
"captcha": "1234",
|
|
"captcha_key": "test-uuid"
|
|
}
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
token = response.json()["data"]["access_token"]
|
|
return {"Authorization": f"Bearer {token}"}
|
|
return {}
|
|
|
|
|
|
@pytest.fixture
|
|
async def admin_headers(client: AsyncClient, test_admin: User, test_password: str) -> dict:
|
|
"""获取管理员认证头"""
|
|
response = await client.post(
|
|
"/api/v1/auth/login",
|
|
json={
|
|
"username": test_admin.username,
|
|
"password": test_password,
|
|
"captcha": "1234",
|
|
"captcha_key": "test-uuid"
|
|
}
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
token = response.json()["data"]["access_token"]
|
|
return {"Authorization": f"Bearer {token}"}
|
|
return {}
|
|
|
|
|
|
# ===== 设备类型相关Fixtures =====
|
|
|
|
@pytest.fixture
|
|
async def test_device_type(db_session: AsyncSession, test_admin: User) -> DeviceType:
|
|
"""创建测试设备类型"""
|
|
device_type = DeviceType(
|
|
type_code="COMPUTER",
|
|
type_name="计算机",
|
|
category="IT设备",
|
|
description="台式机、笔记本等",
|
|
icon="computer",
|
|
status="active",
|
|
sort_order=1,
|
|
created_by=test_admin.id
|
|
)
|
|
db_session.add(device_type)
|
|
await db_session.flush()
|
|
await db_session.refresh(device_type)
|
|
return device_type
|
|
|
|
|
|
@pytest.fixture
|
|
async def test_device_type_with_fields(
|
|
db_session: AsyncSession,
|
|
test_device_type: DeviceType,
|
|
test_admin: User
|
|
) -> DeviceType:
|
|
"""创建带字段的测试设备类型"""
|
|
fields = [
|
|
DeviceTypeField(
|
|
device_type_id=test_device_type.id,
|
|
field_code="cpu",
|
|
field_name="CPU型号",
|
|
field_type="text",
|
|
is_required=True,
|
|
placeholder="例如: Intel i5-10400",
|
|
validation_rules={"max_length": 100},
|
|
sort_order=1,
|
|
created_by=test_admin.id
|
|
),
|
|
DeviceTypeField(
|
|
device_type_id=test_device_type.id,
|
|
field_code="memory",
|
|
field_name="内存容量",
|
|
field_type="select",
|
|
is_required=True,
|
|
options=[
|
|
{"label": "8GB", "value": "8"},
|
|
{"label": "16GB", "value": "16"},
|
|
{"label": "32GB", "value": "32"}
|
|
],
|
|
sort_order=2,
|
|
created_by=test_admin.id
|
|
),
|
|
DeviceTypeField(
|
|
device_type_id=test_device_type.id,
|
|
field_code="disk",
|
|
field_name="硬盘容量",
|
|
field_type="text",
|
|
is_required=False,
|
|
placeholder="例如: 512GB SSD",
|
|
sort_order=3,
|
|
created_by=test_admin.id
|
|
)
|
|
]
|
|
|
|
for field in fields:
|
|
db_session.add(field)
|
|
|
|
await db_session.flush()
|
|
return test_device_type
|
|
|
|
|
|
# ===== 辅助函数Fixtures =====
|
|
|
|
@pytest.fixture
|
|
def sample_asset_data(test_device_type: DeviceType) -> dict:
|
|
"""示例资产数据"""
|
|
return {
|
|
"asset_name": "测试资产",
|
|
"device_type_id": test_device_type.id,
|
|
"organization_id": 1,
|
|
"model": "测试型号",
|
|
"serial_number": f"SN{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
"purchase_date": "2024-01-15",
|
|
"purchase_price": 5000.00,
|
|
"warranty_period": 24,
|
|
"location": "测试位置",
|
|
"dynamic_attributes": {
|
|
"cpu": "Intel i5-10400",
|
|
"memory": "16",
|
|
"disk": "512GB SSD"
|
|
}
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_device_type_data() -> dict:
|
|
"""示例设备类型数据"""
|
|
return {
|
|
"type_code": "LAPTOP",
|
|
"type_name": "笔记本电脑",
|
|
"category": "IT设备",
|
|
"description": "笔记本电脑类",
|
|
"icon": "laptop",
|
|
"sort_order": 1
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_field_data() -> dict:
|
|
"""示例字段数据"""
|
|
return {
|
|
"field_code": "gpu",
|
|
"field_name": "显卡型号",
|
|
"field_type": "text",
|
|
"is_required": False,
|
|
"placeholder": "例如: GTX 1660Ti",
|
|
"validation_rules": {"max_length": 100},
|
|
"sort_order": 4
|
|
}
|