08ea5fbe98
添加用户管理视图、API和状态管理文件
286 lines
12 KiB
Python
286 lines
12 KiB
Python
"""
|
|
文件上传下载功能测试 - TDD Red阶段
|
|
|
|
测试文件上传、下载、验证和管理功能。
|
|
"""
|
|
|
|
import pytest
|
|
import allure
|
|
import os
|
|
import tempfile
|
|
from typing import Any, Optional
|
|
|
|
|
|
@allure.epic("核心框架")
|
|
@allure.feature("文件上传下载功能 - TDD Red阶段")
|
|
class TestFileHandler:
|
|
"""文件处理功能测试类 - TDD Red阶段(期望失败)"""
|
|
|
|
@allure.title("测试文件上传 - TDD Red阶段")
|
|
@allure.description("验证文件上传功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_file_upload(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件上传
|
|
|
|
预期结果:
|
|
- 能够上传文件
|
|
- 返回上传结果和文件信息
|
|
- 支持多种文件类型
|
|
"""
|
|
from core.file_handler import FileUploader
|
|
|
|
with allure.step("Step 1: 创建文件上传器"):
|
|
uploader = FileUploader(upload_dir="/tmp/test_uploads")
|
|
allure.attach("✅ 创建文件上传器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 创建测试文件"):
|
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
|
|
f.write("测试文件内容")
|
|
test_file_path = f.name
|
|
allure.attach(f"✅ 创建测试文件: {test_file_path}", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 上传文件"):
|
|
with open(test_file_path, 'rb') as f:
|
|
result = uploader.upload(f, filename="test.txt")
|
|
allure.attach(f"✅ 上传结果: {result}", "步骤3", allure.attachment_type.TEXT)
|
|
assert result.success is True, "文件上传应该成功"
|
|
assert result.file_id is not None, "应该有文件ID"
|
|
|
|
with allure.step("Step 4: 清理"):
|
|
os.unlink(test_file_path)
|
|
if result.file_path and os.path.exists(result.file_path):
|
|
os.unlink(result.file_path)
|
|
|
|
@allure.title("测试文件下载 - TDD Red阶段")
|
|
@allure.description("验证文件下载功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_file_download(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件下载
|
|
|
|
预期结果:
|
|
- 能够下载已上传的文件
|
|
- 返回文件内容
|
|
- 支持断点续传
|
|
"""
|
|
from core.file_handler import FileUploader, FileDownloader
|
|
|
|
with allure.step("Step 1: 上传测试文件"):
|
|
uploader = FileUploader(upload_dir="/tmp/test_uploads")
|
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
|
|
f.write("下载测试内容")
|
|
test_file_path = f.name
|
|
|
|
with open(test_file_path, 'rb') as f:
|
|
upload_result = uploader.upload(f, filename="download_test.txt")
|
|
allure.attach("✅ 上传测试文件", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 下载文件"):
|
|
# 使用同一个存储管理器
|
|
downloader = FileDownloader(storage_manager=uploader._storage)
|
|
download_result = downloader.download(upload_result.file_id)
|
|
allure.attach(f"✅ 下载结果: {download_result.success}", "步骤2", allure.attachment_type.TEXT)
|
|
assert download_result.success is True, "文件下载应该成功"
|
|
|
|
with allure.step("Step 3: 验证文件内容"):
|
|
content = download_result.content.decode('utf-8')
|
|
assert content == "下载测试内容", f"文件内容不匹配: {content}"
|
|
allure.attach(f"✅ 文件内容验证通过", "步骤3", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 4: 清理"):
|
|
os.unlink(test_file_path)
|
|
|
|
@allure.title("测试文件类型验证 - TDD Red阶段")
|
|
@allure.description("验证文件类型检查功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_file_type_validation(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件类型验证
|
|
|
|
预期结果:
|
|
- 允许合法文件类型
|
|
- 拒绝非法文件类型
|
|
- 支持MIME类型检查
|
|
"""
|
|
from core.file_handler import FileUploader, FileTypeValidator
|
|
|
|
with allure.step("Step 1: 创建文件类型验证器"):
|
|
validator = FileTypeValidator(allowed_extensions=['.txt', '.pdf', '.jpg'])
|
|
allure.attach("✅ 创建文件类型验证器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试合法文件类型"):
|
|
is_valid = validator.validate("document.txt")
|
|
allure.attach(f"✅ txt文件验证: {is_valid}", "步骤2", allure.attachment_type.TEXT)
|
|
assert is_valid is True, "txt文件应该被允许"
|
|
|
|
with allure.step("Step 3: 测试非法文件类型"):
|
|
is_valid = validator.validate("script.exe")
|
|
allure.attach(f"✅ exe文件验证: {is_valid}", "步骤3", allure.attachment_type.TEXT)
|
|
assert is_valid is False, "exe文件应该被拒绝"
|
|
|
|
@allure.title("测试文件大小限制 - TDD Red阶段")
|
|
@allure.description("验证文件大小限制功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_file_size_limit(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件大小限制
|
|
|
|
预期结果:
|
|
- 允许小于限制的文件
|
|
- 拒绝超过限制的文件
|
|
"""
|
|
from core.file_handler import FileUploader, FileSizeValidator
|
|
|
|
with allure.step("Step 1: 创建文件大小验证器"):
|
|
validator = FileSizeValidator(max_size=1024) # 1KB
|
|
allure.attach("✅ 创建文件大小验证器(max_size=1KB)", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试小文件"):
|
|
is_valid = validator.validate(512) # 512 bytes
|
|
allure.attach(f"✅ 512字节文件: {is_valid}", "步骤2", allure.attachment_type.TEXT)
|
|
assert is_valid is True, "小文件应该被允许"
|
|
|
|
with allure.step("Step 3: 测试大文件"):
|
|
is_valid = validator.validate(2048) # 2KB
|
|
allure.attach(f"✅ 2KB文件: {is_valid}", "步骤3", allure.attachment_type.TEXT)
|
|
assert is_valid is False, "大文件应该被拒绝"
|
|
|
|
@allure.title("测试文件名安全验证 - TDD Red阶段")
|
|
@allure.description("验证文件名安全检查功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_filename_security(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件名安全验证
|
|
|
|
预期结果:
|
|
- 检测路径遍历攻击
|
|
- 过滤危险字符
|
|
- 生成安全文件名
|
|
"""
|
|
from core.file_handler import FilenameSanitizer
|
|
|
|
with allure.step("Step 1: 创建文件名净化器"):
|
|
sanitizer = FilenameSanitizer()
|
|
allure.attach("✅ 创建文件名净化器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试路径遍历攻击"):
|
|
safe_name = sanitizer.sanitize("../../../etc/passwd")
|
|
allure.attach(f"✅ 净化结果: {safe_name}", "步骤2", allure.attachment_type.TEXT)
|
|
assert ".." not in safe_name, "路径遍历应该被阻止"
|
|
|
|
with allure.step("Step 3: 测试危险字符"):
|
|
safe_name = sanitizer.sanitize("file;rm -rf /|.txt")
|
|
allure.attach(f"✅ 净化结果: {safe_name}", "步骤3", allure.attachment_type.TEXT)
|
|
assert ";" not in safe_name and "|" not in safe_name, "危险字符应该被移除"
|
|
|
|
@allure.title("测试文件存储管理 - TDD Red阶段")
|
|
@allure.description("验证文件存储管理功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_file_storage_management(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件存储管理
|
|
|
|
预期结果:
|
|
- 支持多种存储后端
|
|
- 文件元数据管理
|
|
- 文件删除和清理
|
|
"""
|
|
from core.file_handler import FileStorageManager
|
|
|
|
with allure.step("Step 1: 创建存储管理器"):
|
|
manager = FileStorageManager(storage_dir="/tmp/test_storage")
|
|
allure.attach("✅ 创建存储管理器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 保存文件"):
|
|
file_id = manager.save("测试内容".encode('utf-8'), filename="test.txt")
|
|
allure.attach(f"✅ 保存文件,ID: {file_id}", "步骤2", allure.attachment_type.TEXT)
|
|
assert file_id is not None, "应该有文件ID"
|
|
|
|
with allure.step("Step 3: 获取文件"):
|
|
content = manager.get(file_id)
|
|
allure.attach(f"✅ 获取文件内容", "步骤3", allure.attachment_type.TEXT)
|
|
assert content == "测试内容".encode('utf-8'), "文件内容应该匹配"
|
|
|
|
with allure.step("Step 4: 删除文件"):
|
|
deleted = manager.delete(file_id)
|
|
allure.attach(f"✅ 删除结果: {deleted}", "步骤4", allure.attachment_type.TEXT)
|
|
assert deleted is True, "文件应该被删除"
|
|
|
|
@allure.title("测试文件批量操作 - TDD Red阶段")
|
|
@allure.description("验证文件批量操作功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_file_batch_operations(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件批量操作
|
|
|
|
预期结果:
|
|
- 支持批量上传
|
|
- 支持批量删除
|
|
- 支持批量下载
|
|
"""
|
|
from core.file_handler import FileUploader
|
|
|
|
with allure.step("Step 1: 创建文件上传器"):
|
|
uploader = FileUploader(upload_dir="/tmp/test_batch")
|
|
allure.attach("✅ 创建文件上传器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 批量上传"):
|
|
files = []
|
|
for i in range(3):
|
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
|
|
f.write(f"文件{i}内容")
|
|
files.append(f.name)
|
|
|
|
results = uploader.upload_batch(files)
|
|
allure.attach(f"✅ 批量上传: {len(results)}个文件", "步骤2", allure.attachment_type.TEXT)
|
|
assert len(results) == 3, "应该上传3个文件"
|
|
|
|
with allure.step("Step 3: 清理"):
|
|
for f in files:
|
|
if os.path.exists(f):
|
|
os.unlink(f)
|
|
|
|
@allure.title("测试文件元数据管理 - TDD Red阶段")
|
|
@allure.description("验证文件元数据管理功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_file_metadata(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试文件元数据管理
|
|
|
|
预期结果:
|
|
- 记录文件元数据
|
|
- 支持元数据查询
|
|
- 支持元数据更新
|
|
"""
|
|
from core.file_handler import FileStorageManager
|
|
|
|
with allure.step("Step 1: 创建存储管理器"):
|
|
manager = FileStorageManager(storage_dir="/tmp/test_metadata")
|
|
allure.attach("✅ 创建存储管理器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 保存文件带元数据"):
|
|
file_id = manager.save(
|
|
"测试内容".encode('utf-8'),
|
|
filename="test.txt",
|
|
metadata={"author": "test_user", "tags": ["test", "demo"]}
|
|
)
|
|
allure.attach(f"✅ 保存文件,ID: {file_id}", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 获取元数据"):
|
|
metadata = manager.get_metadata(file_id)
|
|
allure.attach(f"✅ 元数据: {metadata}", "步骤3", allure.attachment_type.TEXT)
|
|
assert metadata is not None, "应该有元数据"
|
|
assert metadata.get("author") == "test_user", "作者信息应该匹配"
|
|
|
|
with allure.step("Step 4: 清理"):
|
|
manager.delete(file_id)
|