0469272bd6
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 9s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 22s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 38s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 1m59s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 33s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m23s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m24s
CI/CD Pipeline / Integration Tests (push) Successful in 2m40s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m31s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m16s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Validate - Style (push) Successful in 3m6s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 47s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m42s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m48s
CI/CD Pipeline / Validate - Security (push) Successful in 5m28s
AI Code Review / AI Code Review (pull_request) Failing after 5m35s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m5s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m22s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m6s
CI/CD Pipeline / Unit Tests (push) Successful in 8m54s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
81 lines
3.8 KiB
Python
81 lines
3.8 KiB
Python
"""#1743 worker 批量重渲判定 + 封面哈希选帧纯函数测试。
|
||
|
||
- should_rerender_for_batch_dedup:批次首版查重率 >20% 才重渲(非批次/重渲版/无查重率不重渲)
|
||
- pick_batch_cover_index:task_id md5 稳定哈希分散候选帧(同任务稳定、跨任务分散)
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import hashlib
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||
for sub in ("apps/worker", "apps/api", "packages", ""):
|
||
p = str(REPO_ROOT / sub) if sub else str(REPO_ROOT)
|
||
if p not in sys.path:
|
||
sys.path.insert(0, p)
|
||
|
||
from worker_app.tasks.generation import ( # noqa: E402
|
||
BATCH_RENDER_SIMILARITY_LIMIT,
|
||
pick_batch_cover_index,
|
||
should_rerender_for_batch_dedup,
|
||
)
|
||
|
||
|
||
class TestShouldRerenderForBatchDedup:
|
||
def test_non_batch_never_rerenders(self):
|
||
"""非批次任务(batch_id 为空)任何查重率都不重渲。"""
|
||
assert should_rerender_for_batch_dedup(batch_id="", render_attempt=0, batch_similarity=0.99) is False
|
||
assert should_rerender_for_batch_dedup(batch_id="", render_attempt=0, batch_similarity=None) is False
|
||
|
||
def test_batch_first_version_over_threshold_rerenders(self):
|
||
"""批次首版(attempt=0)查重率 >20% → 重渲。"""
|
||
assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.601) is True
|
||
assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.21) is True
|
||
|
||
def test_batch_first_version_under_threshold_no_rerender(self):
|
||
"""批次首版查重率 ≤20% → 不重渲。"""
|
||
assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.20) is False
|
||
assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.0) is False
|
||
assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.05) is False
|
||
|
||
def test_rerendered_version_never_rerenders_again(self):
|
||
"""重渲版(attempt=1)即使仍超阈值也不再重渲(最多重渲一次)。"""
|
||
assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=1, batch_similarity=0.99) is False
|
||
|
||
def test_missing_similarity_no_rerender(self):
|
||
"""查重率缺失(None,非批次查重路径)→ 不重渲。"""
|
||
assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=None) is False
|
||
|
||
def test_threshold_constant_is_20_percent(self):
|
||
assert BATCH_RENDER_SIMILARITY_LIMIT == 0.20
|
||
|
||
|
||
class TestPickBatchCoverIndex:
|
||
def test_stable_for_same_task(self):
|
||
"""同一 task_id 多次调用结果稳定(重试封面不变)。"""
|
||
first = pick_batch_cover_index("task-abc", 3)
|
||
for _ in range(5):
|
||
assert pick_batch_cover_index("task-abc", 3) == first
|
||
|
||
def test_zero_or_one_candidate_returns_zero(self):
|
||
assert pick_batch_cover_index("task-x", 0) == 0
|
||
assert pick_batch_cover_index("task-x", 1) == 0
|
||
|
||
def test_index_within_range(self):
|
||
for i in range(20):
|
||
idx = pick_batch_cover_index(f"task-{i}", 3)
|
||
assert 0 <= idx < 3
|
||
|
||
def test_matches_md5_formula(self):
|
||
"""与主流程公式一致:md5(task_id) % 候选数。"""
|
||
task_id = "task-formula-check"
|
||
expected = int(hashlib.md5(task_id.encode()).hexdigest(), 16) % 3
|
||
assert pick_batch_cover_index(task_id, 3) == expected
|
||
|
||
def test_batch_tasks_spread_across_frames(self):
|
||
"""30 个批次任务在 3 个候选帧上分散(不能全部落在 frame_0——旧 bug 回归守卫)。"""
|
||
indexes = {pick_batch_cover_index(f"batch-task-{i}", 3) for i in range(30)}
|
||
assert len(indexes) >= 2, f"封面帧应分散到多个帧位,实际全部落在: {indexes}"
|