Files
xiaoxia-saas/tests/unit/test_pixel_perturbation.py
T
saas-backend-agent cd6d8615e6
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 (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
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 (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
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 / 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 30s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 30s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m40s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m38s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m5s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m30s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m50s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m30s
AI Code Review / AI Code Review (pull_request) Successful in 6m41s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m34s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 9s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m37s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 20m16s
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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 5s
test: #1765 补充 int seed 分支测试,diff coverage 达标
新增 5 个测试覆盖 int seed 入参分支(reproducible/与 Random 对象
等价/None 默认),满足 diff coverage ≥60% 要求。
2026-09-07 22:47:22 +08:00

142 lines
5.1 KiB
Python

"""像素级扰动滤镜单元测试(Issue #1765)。
覆盖:
- generate_pixel_perturbation:生成像素级扰动参数
- 滤镜组合:2-3 种滤镜随机组合
- 参数范围:肉眼不可见但帧级可检测
- FFmpeg 滤镜语法生成
"""
from __future__ import annotations
import random
import pytest
from packages.domain.variant_plan_selector import generate_pixel_perturbation
class TestGeneratePixelPerturbation:
"""generate_pixel_perturbation 测试。"""
def test_returns_dict(self):
"""返回 dict。"""
result = generate_pixel_perturbation()
assert isinstance(result, dict)
def test_has_filters_key(self):
"""包含 filters 键。"""
result = generate_pixel_perturbation()
assert "filters" in result
def test_filters_count_2_or_3(self):
"""选 2-3 种滤镜。"""
for _ in range(50):
result = generate_pixel_perturbation()
assert len(result["filters"]) in [2, 3]
def test_filters_from_valid_options(self):
"""滤镜来自有效选项。"""
valid_options = {"noise", "unsharp", "curves", "color_balance"}
for _ in range(50):
result = generate_pixel_perturbation()
for f in result["filters"]:
assert f in valid_options
def test_noise_parameters(self):
"""noise 滤镜有正确参数范围。"""
for _ in range(20):
result = generate_pixel_perturbation()
if "noise" in result["filters"]:
strength = result.get("noise_strength", 0)
assert 0.01 <= strength <= 0.02
def test_unsharp_parameters(self):
"""unsharp 滤镜有正确参数范围。"""
for _ in range(20):
result = generate_pixel_perturbation()
if "unsharp" in result["filters"]:
amount = result.get("unsharp_amount", 0)
assert -0.5 <= amount <= 0.5
def test_curves_parameters(self):
"""curves 滤镜有正确参数范围。"""
for _ in range(20):
result = generate_pixel_perturbation()
if "curves" in result["filters"]:
contrast = result.get("curves_contrast", 1.0)
assert 0.95 <= contrast <= 1.05
def test_color_balance_parameters(self):
"""color_balance 滤镜有正确参数范围。"""
valid_colors = [-5, -3, 0, 3, 5]
for _ in range(20):
result = generate_pixel_perturbation()
if "color_balance" in result["filters"]:
assert result.get("color_r") in valid_colors
assert result.get("color_g") in valid_colors
assert result.get("color_b") in valid_colors
def test_same_seed_same_result(self):
"""相同 seed 返回相同结果。"""
rng1 = random.Random(42)
rng2 = random.Random(42)
result1 = generate_pixel_perturbation(rng1)
result2 = generate_pixel_perturbation(rng2)
assert result1 == result2
def test_different_seeds_may_differ(self):
"""不同 seed 可能返回不同结果。"""
results = set()
for seed in range(20):
rng = random.Random(seed)
result = generate_pixel_perturbation(rng)
results.add(tuple(result["filters"]))
# 20 个 seed 至少看到 3 种不同组合
assert len(results) >= 3
class TestPixelPerturbationAcceptance:
"""Issue #1765 验收测试。"""
def test_batch_3_variants_have_different_filters(self):
"""批量 3 个变体有不同的滤镜组合。"""
results = []
for seed in [100, 200, 300]:
rng = random.Random(seed)
result = generate_pixel_perturbation(rng)
results.append(tuple(result["filters"]))
# 至少 2 种不同组合
unique = len(set(results))
assert unique >= 2, f"Expected >= 2 unique filter combos, got {unique}: {results}"
class TestIntSeedSupport:
"""int seed 入参支持(与 get_rhythm_template(seed) 接口一致)。"""
def test_int_seed_returns_dict(self):
"""int seed 正常返回 dict。"""
result = generate_pixel_perturbation(42)
assert isinstance(result, dict)
assert "filters" in result
def test_int_seed_reproducible(self):
"""相同 int seed 结果一致。"""
assert generate_pixel_perturbation(42) == generate_pixel_perturbation(42)
def test_int_seed_differs_across_seeds(self):
"""不同 int seed 大概率不同(遍历确认至少 2 种组合)。"""
results = {tuple(generate_pixel_perturbation(s)["filters"]) for s in range(30)}
assert len(results) >= 2
def test_int_seed_matches_random_obj(self):
"""int seed 与等价 random.Random(seed) 结果一致。"""
assert generate_pixel_perturbation(7) == generate_pixel_perturbation(random.Random(7))
def test_none_seed_works(self):
"""None 入参(默认随机)正常返回。"""
result = generate_pixel_perturbation(None)
assert isinstance(result, dict)
assert len(result["filters"]) in [2, 3]