test(#1743): 修复 smart-match 随机噪声引发的确定性排序断言
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) 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 Web 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 3s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
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 / PR Build API Image (pull_request) Successful in 14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 15s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m22s
AI Code Review / AI Code Review (pull_request) Successful in 1m31s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m35s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 1m53s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m54s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m49s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m7s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m31s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 14m41s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 9s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 7s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m30s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) 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 Web 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 3s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
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 / PR Build API Image (pull_request) Successful in 14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 15s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m22s
AI Code Review / AI Code Review (pull_request) Successful in 1m31s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m35s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 1m53s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m54s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m49s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m7s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m31s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 14m41s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 9s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 7s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m30s
CI Unit Tests 暴露(沙箱 httpx2 无法 collect test_smart_match*.py 未本地复现): - test_smart_match_fallback test_limit_backfills: second(quality=40)/third(30) 质量项仅差 4 分 < 噪声 20,third 可翻到首位 → second 质量提至 90(差 24>20), 200 seeds 验证零翻转 - test_smart_match test_returns_sorted_by_score_descending / test_image_assets: smart_select_assets 直接调用处注入零噪声 rng(_ZeroNoiseRandom),验证纯评分排序 - 验证生产噪声行为:大分差素材排名稳定、同分素材组合随机
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""Tests for packages/domain/smart_match.py — 统一智能选素材算法。"""
|
||||
|
||||
import random
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any
|
||||
@@ -7,6 +8,7 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from packages.domain.smart_match import (
|
||||
SCORE_RANDOM_NOISE_MAX,
|
||||
SmartMatchResult,
|
||||
_diversity_select,
|
||||
_duration_bucket,
|
||||
@@ -46,6 +48,22 @@ class FakeAsset:
|
||||
NOW = datetime(2026, 8, 5, 12, 0, 0, tzinfo=timezone.utc)
|
||||
|
||||
|
||||
class _ZeroNoiseRandom(random.Random):
|
||||
"""零噪声随机源:uniform(0, NOISE_MAX) 恒返回 0,使「按评分降序」类断言确定可复现。
|
||||
|
||||
smart_select_assets 生产环境注入随机噪声(同分素材每次选出不同组合,#1743);
|
||||
验证纯评分排序的单测用本随机源消除排序随机性。
|
||||
"""
|
||||
|
||||
def uniform(self, a, b):
|
||||
if a == 0.0 and b == SCORE_RANDOM_NOISE_MAX:
|
||||
return 0.0
|
||||
return super().uniform(a, b)
|
||||
|
||||
|
||||
_ZERO_NOISE = _ZeroNoiseRandom(0)
|
||||
|
||||
|
||||
# ── score_asset tests ────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -185,7 +203,7 @@ class TestSmartSelectAssets:
|
||||
FakeAsset(id="high", quality_score=95, duration=15),
|
||||
FakeAsset(id="mid", quality_score=60, duration=15),
|
||||
]
|
||||
results = smart_select_assets(assets)
|
||||
results = smart_select_assets(assets, rng=_ZERO_NOISE)
|
||||
scores = [r.score for r in results]
|
||||
assert scores == sorted(scores, reverse=True)
|
||||
assert results[0].asset.id == "high"
|
||||
@@ -234,7 +252,7 @@ class TestSmartSelectAssets:
|
||||
FakeAsset(id="img1", mime_type="image/jpeg", quality_score=90, duration=None),
|
||||
FakeAsset(id="img2", mime_type="image/png", quality_score=70, duration=None),
|
||||
]
|
||||
results = smart_select_assets(assets, kind="image")
|
||||
results = smart_select_assets(assets, kind="image", rng=_ZERO_NOISE)
|
||||
assert len(results) == 2
|
||||
assert results[0].asset.id == "img1"
|
||||
|
||||
|
||||
@@ -155,7 +155,9 @@ class TestSmartMatchAvailabilityFallback:
|
||||
project = Project(id="proj-1", name="Test", owner_user_id="user-1")
|
||||
assets = [
|
||||
_video_asset("top-exhausted.mp4", quality=100, used_ranges=_exhausted_ranges(15)),
|
||||
_video_asset("second-fresh.mp4", quality=40, used_ranges=None),
|
||||
# second 质量分显著高于 third(质量项差 (90-30)*0.4=24 > 噪声上限 20),
|
||||
# 排除耗尽素材后 second 稳定排首位回补(噪声不影响大分差排名)
|
||||
_video_asset("second-fresh.mp4", quality=90, used_ranges=None),
|
||||
_video_asset("third-fresh.mp4", quality=30, used_ranges=None),
|
||||
]
|
||||
repo = _StubAssetRepo(assets)
|
||||
|
||||
Reference in New Issue
Block a user