Files
disknext/tests/README.md
于小丘 f93cb3eedb Add unit tests for models and services
- Implemented unit tests for Object model including folder and file creation, properties, and path retrieval.
- Added unit tests for Setting model covering creation, unique constraints, and type enumeration.
- Created unit tests for User model focusing on user creation, uniqueness, and group relationships.
- Developed unit tests for Login service to validate login functionality, including 2FA and token generation.
- Added utility tests for JWT creation and verification, ensuring token integrity and expiration handling.
- Implemented password utility tests for password generation, hashing, and TOTP verification.
2025-12-19 19:48:05 +08:00

247 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DiskNext Server 单元测试文档
## 测试结构
```
tests/
├── conftest.py # Pytest 配置和 fixtures
├── unit/ # 单元测试
│ ├── models/ # 模型层测试
│ │ ├── test_base.py # TableBase/UUIDTableBase 测试
│ │ ├── test_user.py # User 模型测试
│ │ ├── test_group.py # Group/GroupOptions 测试
│ │ ├── test_object.py # Object 模型测试
│ │ └── test_setting.py # Setting 模型测试
│ ├── utils/ # 工具层测试
│ │ ├── test_password.py # Password 工具测试
│ │ └── test_jwt.py # JWT 工具测试
│ └── service/ # 服务层测试
│ └── test_login.py # Login 服务测试
└── README.md # 本文档
```
## 运行测试
### 安装依赖
```bash
# 使用 uv (推荐)
uv sync
# 或使用 pip
pip install -e .
```
### 运行所有测试
```bash
pytest
```
### 运行特定测试文件
```bash
# 测试模型层
pytest tests/unit/models/test_base.py
# 测试用户模型
pytest tests/unit/models/test_user.py
# 测试工具层
pytest tests/unit/utils/test_password.py
# 测试服务层
pytest tests/unit/service/test_login.py
```
### 运行特定测试函数
```bash
pytest tests/unit/models/test_base.py::test_table_base_add_single
```
### 运行带覆盖率的测试
```bash
# 生成覆盖率报告
pytest --cov
# 生成 HTML 覆盖率报告
pytest --cov --cov-report=html
# 查看 HTML 报告
# 打开 htmlcov/index.html
```
### 并行测试
```bash
# 使用所有 CPU 核心
pytest -n auto
# 使用指定数量的核心
pytest -n 4
```
## Fixtures 说明
### 数据库相关
- `test_engine`: 内存 SQLite 数据库引擎
- `initialized_db`: 已初始化表结构的数据库
- `db_session`: 数据库会话(每个测试函数独立)
### 用户相关(在 conftest.py 中已提供)
- `test_user`: 创建测试用户,返回 {id, username, password, token, group_id, policy_id}
- `admin_user`: 创建管理员用户
- `auth_headers`: 测试用户的认证请求头
- `admin_headers`: 管理员的认证请求头
### 数据相关
- `test_directory`: 为测试用户创建目录结构
## 测试覆盖范围
### 模型层 (tests/unit/models/)
#### test_base.py - TableBase/UUIDTableBase
- ✅ 单条记录创建
- ✅ 批量创建
- ✅ save() 方法
- ✅ update() 方法
- ✅ delete() 方法
- ✅ get() 三种 fetch_mode
- ✅ offset/limit 分页
- ✅ get_exist_one() 存在/不存在场景
- ✅ UUID 自动生成
- ✅ 时间戳自动维护
#### test_user.py - User 模型
- ✅ 创建用户
- ✅ 用户名唯一约束
- ✅ to_public() DTO 转换
- ✅ 用户与用户组关系
- ✅ status 默认值
- ✅ storage 默认值
- ✅ ThemeType 枚举
#### test_group.py - Group/GroupOptions 模型
- ✅ 创建用户组
- ✅ 用户组与选项一对一关系
- ✅ to_response() DTO 转换
- ✅ 多对多关系policies
#### test_object.py - Object 模型
- ✅ 创建目录
- ✅ 创建文件
- ✅ is_file 属性
- ✅ is_folder 属性
- ✅ get_root() 方法
- ✅ get_by_path() 根目录
- ✅ get_by_path() 嵌套路径
- ✅ get_by_path() 路径不存在
- ✅ get_children() 方法
- ✅ 父子关系
- ✅ 同目录名称唯一约束
#### test_setting.py - Setting 模型
- ✅ 创建设置
- ✅ type+name 唯一约束
- ✅ SettingsType 枚举
- ✅ 更新设置值
### 工具层 (tests/unit/utils/)
#### test_password.py - Password 工具
- ✅ 默认长度生成密码
- ✅ 自定义长度生成密码
- ✅ 密码哈希
- ✅ 正确密码验证
- ✅ 错误密码验证
- ✅ TOTP 密钥生成
- ✅ TOTP 验证正确
- ✅ TOTP 验证错误
#### test_jwt.py - JWT 工具
- ✅ 访问令牌创建
- ✅ 自定义过期时间
- ✅ 刷新令牌创建
- ✅ 令牌解码
- ✅ 令牌过期
- ✅ 无效签名
### 服务层 (tests/unit/service/)
#### test_login.py - Login 服务
- ✅ 正常登录
- ✅ 用户不存在
- ✅ 密码错误
- ✅ 用户被封禁
- ✅ 需要 2FA
- ✅ 2FA 错误
- ✅ 2FA 成功
## 常见问题
### 1. 数据库连接错误
所有测试使用内存 SQLite 数据库,不需要外部数据库服务。
### 2. 导入错误
确保从项目根目录运行测试:
```bash
cd c:\Users\Administrator\Documents\Code\Server
pytest
```
### 3. 异步测试错误
项目已配置 `pytest-asyncio`,使用 `@pytest.mark.asyncio` 装饰器即可。
### 4. Fixture 依赖错误
检查 conftest.py 中是否定义了所需的 fixture确保使用正确的参数名。
## 编写新测试
### 模板
```python
"""
模块名称的单元测试
"""
import pytest
from sqlmodel.ext.asyncio.session import AsyncSession
from models.xxx import YourModel
@pytest.mark.asyncio
async def test_your_feature(db_session: AsyncSession):
"""测试功能描述"""
# 准备数据
instance = YourModel(field="value")
instance = await instance.save(db_session)
# 执行操作
result = await YourModel.get(db_session, YourModel.id == instance.id)
# 断言验证
assert result is not None
assert result.field == "value"
```
## 持续集成
项目配置了覆盖率要求80%),确保新代码有足够的测试覆盖。
```bash
# 检查覆盖率是否达标
pytest --cov --cov-fail-under=80
```