1a57878f76
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 1m12s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 2m17s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 1m33s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 3m14s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
1. 未使用依赖清理:
- 从 requirements-base.txt 移除 cryptography 和 pyOpenSSL
2. pyflakes 警告清零 (apps/ + packages/ + tests/):
- 移除 17 处未使用的 import (F401)
- 修复 26 处未使用的局部变量 (F841):
* 有副作用的赋值转为裸调用
* 无副作用的赋值直接删除
- 修复 1 处未使用的异常变量 (F841)
- 修复 1 处空 except 块
3. 测试文件冗余清理:
- 删除 tests/integration/test_project_management.py (模块级 skip,测试不存在的模块)
- 删除 tests/integration/fixtures/duplication_routes_fixed.py (未被引用)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
204 lines
7.8 KiB
Python
204 lines
7.8 KiB
Python
"""UUID 字段长度单元测试 — 验证标准 UUID(带横杠,36字符)可正常插入.
|
||
|
||
覆盖:
|
||
- 所有从 varchar(32) 扩到 varchar(36) 的表
|
||
- 插入标准 UUID 格式(带横杠)不报 StringDataRightTruncation
|
||
- 字段长度从 32 扩到 36 后 ORM 模型定义正确
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import uuid
|
||
|
||
import pytest
|
||
|
||
from packages.adapters.sqlalchemy_impl.models import (
|
||
ClassificationJobModel,
|
||
EditPlanClipModel,
|
||
EditPlanModel,
|
||
EditTemplateModel,
|
||
GeneratedVideoModel,
|
||
GenerationTaskModel,
|
||
IngestJobModel,
|
||
JobModel,
|
||
ProjectModel,
|
||
TemplateClipConfigModel,
|
||
)
|
||
|
||
|
||
def _uuid() -> str:
|
||
"""生成标准 UUID 字符串(带横杠,36 字符)."""
|
||
return str(uuid.uuid4())
|
||
|
||
|
||
class TestUUIDFieldLengthModels:
|
||
"""验证 ORM 模型中 UUID 字段定义为 String(36)."""
|
||
|
||
def _get_column_type_length(self, model_cls, column_name: str) -> int:
|
||
"""获取模型列的 String 长度."""
|
||
col = model_cls.__table__.columns[column_name]
|
||
return col.type.length
|
||
|
||
# ── ProjectModel ──────────────────────────────────────────────────────────
|
||
|
||
def test_project_id_is_36(self):
|
||
assert self._get_column_type_length(ProjectModel, "id") == 36
|
||
|
||
def test_project_owner_user_id_is_36(self):
|
||
assert self._get_column_type_length(ProjectModel, "owner_user_id") == 36
|
||
|
||
# ── EditTemplateModel ─────────────────────────────────────────────────────
|
||
|
||
def test_edit_template_id_is_36(self):
|
||
assert self._get_column_type_length(EditTemplateModel, "id") == 36
|
||
|
||
# ── EditPlanModel ─────────────────────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize(
|
||
"col",
|
||
["id", "template_id", "source_edit_plan_id", "project_id", "created_by_user_id"],
|
||
)
|
||
def test_edit_plan_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(EditPlanModel, col) == 36
|
||
|
||
# ── TemplateClipConfigModel ───────────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize("col", ["id", "template_id"])
|
||
def test_template_clip_config_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(TemplateClipConfigModel, col) == 36
|
||
|
||
# ── EditPlanClipModel ─────────────────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize(
|
||
"col",
|
||
["id", "plan_id", "template_clip_config_id", "asset_id"],
|
||
)
|
||
def test_edit_plan_clip_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(EditPlanClipModel, col) == 36
|
||
|
||
# ── IngestJobModel(P0 bug 所在表)─────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize(
|
||
"col",
|
||
["id", "project_id", "library_id", "result_asset_id"],
|
||
)
|
||
def test_ingest_job_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(IngestJobModel, col) == 36
|
||
|
||
def test_ingest_job_library_id_accepts_standard_uuid(self):
|
||
"""P0 回归:library_id 必须能容纳标准 UUID(36 字符带横杠)."""
|
||
standard_uuid = "550e8400-e29b-41d4-a716-446655440000"
|
||
assert len(standard_uuid) == 36
|
||
col = IngestJobModel.__table__.columns["library_id"]
|
||
assert col.type.length >= 36
|
||
|
||
# ── ClassificationJobModel ────────────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize("col", ["id", "project_id", "asset_id"])
|
||
def test_classification_job_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(ClassificationJobModel, col) == 36
|
||
|
||
# ── GenerationTaskModel ───────────────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize(
|
||
"col",
|
||
[
|
||
"id",
|
||
"project_id",
|
||
"strategy_id",
|
||
"asset_library_id",
|
||
"voice_library_id",
|
||
"created_by_user_id",
|
||
"source_edit_plan_id",
|
||
"batch_id",
|
||
],
|
||
)
|
||
def test_generation_task_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(GenerationTaskModel, col) == 36
|
||
|
||
# ── GeneratedVideoModel ───────────────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize(
|
||
"col",
|
||
["id", "project_id", "generation_task_id", "duplicate_of"],
|
||
)
|
||
def test_generated_video_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(GeneratedVideoModel, col) == 36
|
||
|
||
# ── JobModel ──────────────────────────────────────────────────────────────
|
||
|
||
@pytest.mark.parametrize(
|
||
"col",
|
||
["id", "project_id", "source_id", "created_by_user_id"],
|
||
)
|
||
def test_job_uuid_fields_are_36(self, col):
|
||
assert self._get_column_type_length(JobModel, col) == 36
|
||
|
||
|
||
class TestUUIDInsertWithHyphens:
|
||
"""验证标准 UUID(带横杠)可构造 ORM 对象,字段长度足够."""
|
||
|
||
def test_ingest_job_model_construct_with_standard_uuid(self):
|
||
"""P0 回归测试:用标准 UUID 构造 IngestJobModel 不报错."""
|
||
std_uuid = _uuid()
|
||
assert len(std_uuid) == 36
|
||
|
||
job = IngestJobModel(
|
||
id=_uuid(),
|
||
project_id=_uuid(),
|
||
library_id=std_uuid, # ← 关键:标准 UUID 带横杠
|
||
storage_key="test/file.mp4",
|
||
result_asset_id=_uuid(),
|
||
)
|
||
assert job.library_id == std_uuid
|
||
assert len(job.library_id) == 36
|
||
|
||
def test_project_model_construct_with_standard_uuid(self):
|
||
project = ProjectModel(
|
||
id=_uuid(),
|
||
owner_user_id=_uuid(),
|
||
name="test",
|
||
)
|
||
assert len(project.id) == 36
|
||
assert len(project.owner_user_id) == 36
|
||
|
||
def test_generation_task_model_construct_with_standard_uuid(self):
|
||
task = GenerationTaskModel(
|
||
id=_uuid(),
|
||
project_id=_uuid(),
|
||
asset_library_id=_uuid(),
|
||
created_by_user_id=_uuid(),
|
||
source_edit_plan_id=_uuid(),
|
||
batch_id=_uuid(),
|
||
)
|
||
assert len(task.id) == 36
|
||
assert len(task.asset_library_id) == 36
|
||
|
||
def test_edit_plan_model_construct_with_standard_uuid(self):
|
||
plan = EditPlanModel(
|
||
id=_uuid(),
|
||
template_id=_uuid(),
|
||
source_edit_plan_id=_uuid(),
|
||
project_id=_uuid(),
|
||
created_by_user_id=_uuid(),
|
||
)
|
||
assert len(plan.id) == 36
|
||
assert len(plan.template_id) == 36
|
||
|
||
def test_generated_video_model_construct_with_standard_uuid(self):
|
||
video = GeneratedVideoModel(
|
||
id=_uuid(),
|
||
project_id=_uuid(),
|
||
generation_task_id=_uuid(),
|
||
duplicate_of=_uuid(),
|
||
name="test.mp4",
|
||
file_url="https://example.com/test.mp4",
|
||
file_size=1000,
|
||
duration=10.0,
|
||
width=1280,
|
||
height=720,
|
||
fps=25.0,
|
||
)
|
||
assert len(video.id) == 36
|
||
assert len(video.duplicate_of) == 36
|