- 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.
247 lines
5.3 KiB
Markdown
247 lines
5.3 KiB
Markdown
# 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
|
||
```
|