- 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.
9.3 KiB
9.3 KiB
DiskNext Server 单元测试实现总结
概述
本次任务完成了 DiskNext Server 项目的单元测试实现,覆盖了模型层、工具层和服务层的核心功能。
实现的测试文件
1. 配置文件
文件: tests/conftest.py
提供了测试所需的所有 fixtures:
-
数据库相关:
test_engine: 内存 SQLite 数据库引擎initialized_db: 已初始化表结构的数据库db_session: 数据库会话(每个测试函数独立)
-
用户相关:
test_user: 创建测试用户admin_user: 创建管理员用户auth_headers: 测试用户的认证请求头admin_headers: 管理员的认证请求头
-
数据相关:
test_directory: 创建测试目录结构
2. 模型层测试 (tests/unit/models/)
test_base.py - TableBase 和 UUIDTableBase 基类测试
测试用例数: 14个
- ✅
test_table_base_add_single- 单条记录创建 - ✅
test_table_base_add_batch- 批量创建 - ✅
test_table_base_save- save() 方法 - ✅
test_table_base_update- update() 方法 - ✅
test_table_base_delete- delete() 方法 - ✅
test_table_base_get_first- get() fetch_mode="first" - ✅
test_table_base_get_one- get() fetch_mode="one" - ✅
test_table_base_get_all- get() fetch_mode="all" - ✅
test_table_base_get_with_pagination- offset/limit 分页 - ✅
test_table_base_get_exist_one_found- 存在时返回 - ✅
test_table_base_get_exist_one_not_found- 不存在时抛出 HTTPException 404 - ✅
test_uuid_table_base_id_generation- UUID 自动生成 - ✅
test_timestamps_auto_update- created_at/updated_at 自动维护
覆盖的核心方法:
add()- 单条和批量添加save()- 保存实例update()- 更新实例delete()- 删除实例get()- 查询(三种模式)get_exist_one()- 查询存在或抛出异常
test_user.py - User 模型测试
测试用例数: 7个
- ✅
test_user_create- 创建用户 - ✅
test_user_unique_username- 用户名唯一约束 - ✅
test_user_to_public- to_public() DTO 转换 - ✅
test_user_group_relationship- 用户与用户组关系 - ✅
test_user_status_default- status 默认值 - ✅
test_user_storage_default- storage 默认值 - ✅
test_user_theme_enum- ThemeType 枚举
覆盖的特性:
- 用户创建和字段验证
- 唯一约束检查
- DTO 转换(排除敏感字段)
- 关系加载(用户组)
- 默认值验证
- 枚举类型使用
test_group.py - Group 和 GroupOptions 模型测试
测试用例数: 4个
- ✅
test_group_create- 创建用户组 - ✅
test_group_options_relationship- 用户组与选项一对一关系 - ✅
test_group_to_response- to_response() DTO 转换 - ✅
test_group_policies_relationship- 多对多关系
覆盖的特性:
- 用户组创建
- 一对一关系(GroupOptions)
- DTO 转换逻辑
- 多对多关系(policies)
test_object.py - Object 模型测试
测试用例数: 12个
- ✅
test_object_create_folder- 创建目录 - ✅
test_object_create_file- 创建文件 - ✅
test_object_is_file_property- is_file 属性 - ✅
test_object_is_folder_property- is_folder 属性 - ✅
test_object_get_root- get_root() 方法 - ✅
test_object_get_by_path_root- 获取根目录 - ✅
test_object_get_by_path_nested- 获取嵌套路径 - ✅
test_object_get_by_path_not_found- 路径不存在 - ✅
test_object_get_children- get_children() 方法 - ✅
test_object_parent_child_relationship- 父子关系 - ✅
test_object_unique_constraint- 同目录名称唯一
覆盖的特性:
- 文件和目录创建
- 属性判断(is_file, is_folder)
- 根目录获取
- 路径解析(支持嵌套)
- 子对象获取
- 父子关系
- 唯一性约束
test_setting.py - Setting 模型测试
测试用例数: 7个
- ✅
test_setting_create- 创建设置 - ✅
test_setting_unique_type_name- type+name 唯一约束 - ✅
test_settings_type_enum- SettingsType 枚举 - ✅
test_setting_update_value- 更新设置值 - ✅
test_setting_nullable_value- value 可为空 - ✅
test_setting_get_by_type_and_name- 通过 type 和 name 查询 - ✅
test_setting_get_all_by_type- 获取某类型的所有设置
覆盖的特性:
- 设置项创建
- 复合唯一约束
- 枚举类型
- 更新操作
- 空值处理
- 复合查询
3. 工具层测试 (tests/unit/utils/)
test_password.py - Password 工具类测试
测试用例数: 10个
- ✅
test_password_generate_default_length- 默认长度生成 - ✅
test_password_generate_custom_length- 自定义长度 - ✅
test_password_hash- 密码哈希 - ✅
test_password_verify_valid- 正确密码验证 - ✅
test_password_verify_invalid- 错误密码验证 - ✅
test_totp_generate- TOTP 密钥生成 - ✅
test_totp_verify_valid- TOTP 验证正确 - ✅
test_totp_verify_invalid- TOTP 验证错误 - ✅
test_password_hash_consistency- 哈希一致性(盐随机) - ✅
test_password_generate_uniqueness- 密码唯一性
覆盖的方法:
Password.generate()- 密码生成Password.hash()- 密码哈希Password.verify()- 密码验证Password.generate_totp()- TOTP 生成Password.verify_totp()- TOTP 验证
test_jwt.py - JWT 工具测试
测试用例数: 10个
- ✅
test_create_access_token- 访问令牌创建 - ✅
test_create_access_token_custom_expiry- 自定义过期时间 - ✅
test_create_refresh_token- 刷新令牌创建 - ✅
test_token_decode- 令牌解码 - ✅
test_token_expired- 令牌过期 - ✅
test_token_invalid_signature- 无效签名 - ✅
test_access_token_does_not_have_token_type- 访问令牌无 token_type - ✅
test_refresh_token_has_token_type- 刷新令牌有 token_type - ✅
test_token_payload_preserved- 自定义负载保留 - ✅
test_create_refresh_token_default_expiry- 默认30天过期
覆盖的方法:
create_access_token()- 访问令牌create_refresh_token()- 刷新令牌- JWT 解码和验证
4. 服务层测试 (tests/unit/service/)
test_login.py - Login 服务测试
测试用例数: 8个
- ✅
test_login_success- 正常登录 - ✅
test_login_user_not_found- 用户不存在 - ✅
test_login_wrong_password- 密码错误 - ✅
test_login_user_banned- 用户被封禁 - ✅
test_login_2fa_required- 需要 2FA - ✅
test_login_2fa_invalid- 2FA 错误 - ✅
test_login_2fa_success- 2FA 成功 - ✅
test_login_case_sensitive_username- 用户名大小写敏感
覆盖的场景:
- 正常登录流程
- 用户不存在
- 密码错误
- 用户状态检查
- 两步验证流程
- 边界情况
测试统计
| 测试模块 | 文件数 | 测试用例数 |
|---|---|---|
| 模型层 | 4 | 44 |
| 工具层 | 2 | 20 |
| 服务层 | 1 | 8 |
| 总计 | 7 | 72 |
技术栈
- 测试框架: pytest
- 异步支持: pytest-asyncio
- 数据库: SQLite (内存)
- ORM: SQLModel
- 覆盖率: pytest-cov
运行测试
快速开始
# 安装依赖
uv sync
# 运行所有测试
pytest
# 运行特定模块
python run_tests.py models
python run_tests.py utils
python run_tests.py service
# 带覆盖率运行
pytest --cov
详细文档
参见 tests/README.md 获取详细的测试文档和使用指南。
测试设计原则
- 隔离性: 每个测试函数使用独立的数据库会话,测试之间互不影响
- 可读性: 使用简体中文 docstring,清晰描述测试目的
- 完整性: 覆盖正常流程、异常流程和边界情况
- 真实性: 使用真实的数据库操作,而非 Mock
- 可维护性: 使用 fixtures 复用测试数据和配置
符合项目规范
- ✅ 使用 Python 3.10+ 类型注解
- ✅ 所有异步测试使用
@pytest.mark.asyncio - ✅ 使用简体中文 docstring
- ✅ 遵循
test_功能_场景命名规范 - ✅ 使用 conftest.py 管理 fixtures
- ✅ 禁止使用 Mock(除非必要)
未来工作
可扩展的测试点
- 集成测试: 测试 API 端点的完整流程
- 性能测试: 使用 pytest-benchmark 测试性能
- 并发测试: 测试并发场景下的数据一致性
- Edge Cases: 更多边界情况和异常场景
建议添加的测试
- Policy 模型的完整测试
- GroupPolicyLink 多对多关系测试
- Object 的文件上传/下载测试
- 更多服务层的业务逻辑测试
注意事项
- SQLite 限制: 内存数据库不支持某些特性(如
onupdate),部分测试可能需要根据实际数据库调整 - Secret Key: JWT 测试使用测试专用密钥,与生产环境隔离
- TOTP 时间敏感: TOTP 测试依赖系统时间,确保系统时钟准确
贡献者指南
编写新测试时:
- 在对应的目录下创建
test_<module>.py文件 - 使用 conftest.py 中的 fixtures
- 遵循现有的命名和结构规范
- 确保测试独立且可重复运行
- 添加清晰的 docstring
总结
本次实现完成了 DiskNext Server 项目的单元测试基础设施,包括:
- ✅ 完整的 pytest 配置
- ✅ 72 个测试用例覆盖核心功能
- ✅ 灵活的 fixtures 系统
- ✅ 详细的测试文档
- ✅ 便捷的测试运行脚本
所有测试均遵循项目规范,使用异步数据库操作,确保测试的真实性和可靠性。