本文档介绍FreeTOP项目的测试体系和使用方法。
tests/
├── unit/ # 单元测试 - 测试单个模块、函数或类
├── integration/ # 集成测试 - 测试模块间交互
├── functional/ # 功能测试 - 测试完整业务功能
├── e2e/ # 端到端测试 - 测试完整用户场景
├── conftest.py # 共享的测试配置和fixtures
├── __init__.py # 测试包初始化
└── README.md # 测试目录说明
# 方法1: 使用测试脚本
python run_tests.py --install-deps
# 方法2: 直接安装
pip install pytest pytest-cov pytest-html pytest-xdist
# 方法3: 使用Makefile(如果支持)
make install-test-deps# 运行所有测试
python run_tests.py
# 或使用pytest直接运行
pytest tests/
# 或使用Makefile
make test目的: 测试单个模块、函数或类的功能,不依赖外部系统。
特点:
- 运行速度快
- 隔离性强
- 易于调试
- 覆盖率高
运行方式:
python run_tests.py --type unit
# 或
pytest tests/unit/
# 或
make test-unit包含测试:
test_user_service.py- 用户服务单元测试test_browser_config.py- 浏览器配置单元测试test_browser_settings_only.py- 浏览器设置单元测试test_fixes.py- 修复效果验证测试
目的: 测试多个模块之间的交互,可能涉及数据库、外部API等。
特点:
- 测试模块间协作
- 可能需要外部依赖
- 运行时间较长
- 发现接口问题
运行方式:
python run_tests.py --type integration
# 或
pytest tests/integration/
# 或
make test-integration包含测试:
test_browser_integration.py- 浏览器集成测试test_browser_connectivity.py- 浏览器连接测试test_playwright_browser.py- Playwright浏览器测试test_crawler.py- 爬虫集成测试- 等等...
目的: 测试完整的业务功能,从用户角度验证系统行为。
特点:
- 业务场景导向
- 端到端流程
- 用户视角
- 验证需求实现
运行方式:
python run_tests.py --type functional
# 或
pytest tests/functional/
# 或
make test-functional包含测试:
test_api_headless.py- API headless功能测试test_gif_api.py- GIF API功能测试test_gif_paths.py- GIF路径功能测试
目的: 测试完整的用户场景,包括前端和后端的完整流程。
特点:
- 完整用户流程
- 真实环境模拟
- 最高置信度
- 运行时间最长
运行方式:
python run_tests.py --type e2e
# 或
pytest tests/e2e/
# 或
make test-e2e包含测试:
test_browser_events.html- 浏览器事件端到端测试
# 终端覆盖率报告
python run_tests.py --coverage
# HTML覆盖率报告
python run_tests.py --html-coverage
# 使用Makefile
make test-coverage
make test-html生成HTML报告后,打开 htmlcov/index.html 文件查看详细的覆盖率信息。
项目使用pytest标记来分类和过滤测试:
# 跳过慢速测试
python run_tests.py --markers "not slow"
# 只运行浏览器相关测试
python run_tests.py --markers "browser"
# 只运行数据库相关测试
python run_tests.py --markers "database"
# 只运行网络相关测试
python run_tests.py --markers "network"可用标记:
unit- 单元测试integration- 集成测试functional- 功能测试e2e- 端到端测试slow- 运行时间较长的测试browser- 需要浏览器的测试database- 需要数据库的测试network- 需要网络连接的测试
项目使用 pytest.ini 文件配置pytest行为:
- 测试发现规则
- 输出格式
- 标记定义
- 警告过滤
tests/conftest.py 提供了共享的测试fixtures:
project_root- 项目根目录temp_dir- 临时目录mock_env_vars- 模拟环境变量mock_request_headers- 模拟请求头mock_user_settings- 模拟用户设置mock_jwt_tokens- 模拟JWT tokens
run_tests.py 提供了便捷的测试执行接口:
# 查看所有选项
python run_tests.py --help
# 常用命令
python run_tests.py --type unit --verbose
python run_tests.py --coverage
python run_tests.py --file tests/unit/test_user_service.py- 测试文件:
test_*.py - 测试类:
Test* - 测试函数:
test_*
def test_function_name():
"""测试描述:说明测试的目的和预期结果"""
# Arrange - 准备测试数据
input_data = "test_input"
expected_result = "expected_output"
# Act - 执行被测试的功能
actual_result = function_under_test(input_data)
# Assert - 验证结果
assert actual_result == expected_resultdef test_with_fixture(mock_user_settings, temp_dir):
"""使用fixtures的测试示例"""
# 使用预定义的mock数据和临时目录
user_id = "test_user_1"
settings = mock_user_settings[user_id]
# 测试逻辑...import pytest
@pytest.mark.parametrize("input_val,expected", [
("desktop", False),
("mobile", True),
("tablet", True),
])
def test_is_mobile_device(input_val, expected):
"""参数化测试移动设备检测"""
result = is_mobile_device(input_val)
assert result == expecteddef test_function_raises_exception():
"""测试异常情况"""
with pytest.raises(ValueError, match="Invalid input"):
function_that_should_raise("invalid_input")项目配置了GitHub Actions来自动运行测试:
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install dependencies
run: |
pip install -r requirements.txt
python run_tests.py --install-deps
- name: Run tests
run: python run_tests.py --coverage# 模拟CI环境运行测试
python run_tests.py --type all --coverage --verbose
# 或使用Makefile
make test-ci# 运行特定测试文件
pytest tests/unit/test_user_service.py
# 运行特定测试函数
pytest tests/unit/test_user_service.py::test_get_user_settings
# 运行特定测试类
pytest tests/unit/test_user_service.py::TestUserService# 详细输出
pytest -v tests/unit/test_user_service.py
# 显示print输出
pytest -s tests/unit/test_user_service.py
# 在第一个失败时停止
pytest -x tests/
# 显示最慢的10个测试
pytest --durations=10 tests/def test_debug_example():
"""调试示例"""
import pdb; pdb.set_trace() # 设置断点
# 测试代码...# 运行时自动进入pdb
pytest --pdb tests/unit/test_user_service.pyimport pytest
@pytest.mark.slow
def test_performance_benchmark():
"""性能基准测试"""
import time
start_time = time.time()
# 执行性能测试的代码
result = expensive_operation()
end_time = time.time()
execution_time = end_time - start_time
# 断言执行时间在可接受范围内
assert execution_time < 1.0 # 1秒内完成
assert result is not Noneimport psutil
import os
def test_memory_usage():
"""内存使用测试"""
process = psutil.Process(os.getpid())
initial_memory = process.memory_info().rss
# 执行可能消耗大量内存的操作
large_data = create_large_dataset()
final_memory = process.memory_info().rss
memory_increase = final_memory - initial_memory
# 断言内存增长在可接受范围内
assert memory_increase < 100 * 1024 * 1024 # 100MB-
导入错误
ModuleNotFoundError: No module named 'src'解决方案:确保在项目根目录运行测试,或检查
conftest.py中的路径配置。 -
数据库连接错误
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table解决方案:确保测试数据库已初始化,或使用内存数据库进行测试。
-
浏览器驱动问题
selenium.common.exceptions.WebDriverException: 'chromedriver' executable needs to be in PATH解决方案:安装并配置浏览器驱动,或使用headless模式。
# 清理测试生成的文件
make clean-test
# 或手动清理
rm -rf htmlcov/
rm -f .coverage
rm -rf .pytest_cache/
find . -name "__pycache__" -type d -exec rm -rf {} +如果你想为项目贡献测试代码:
- 确保新功能有对应的测试
- 保持测试覆盖率不下降
- 遵循项目的测试规范
- 运行完整测试套件确保没有破坏现有功能
- 在PR中说明测试策略和覆盖的场景
# 提交前运行完整测试
python run_tests.py --coverage