| """ |
| Unit tests for the ensemble scoring module. |
| """ |
| import pytest |
| from backend.app.services.ensemble import compute_ensemble, calibrate_weights |
|
|
|
|
| class TestComputeEnsemble: |
| def test_all_signals_provided(self): |
| result = compute_ensemble( |
| p_ai=0.8, s_perp=0.6, s_embed_cluster=0.4, |
| p_ext=0.3, s_styl=0.5, p_watermark=0.0 |
| ) |
| assert "threat_score" in result |
| assert "explainability" in result |
| assert 0.0 <= result["threat_score"] <= 1.0 |
| assert len(result["explainability"]) == 6 |
|
|
| def test_partial_signals(self): |
| result = compute_ensemble(p_ai=0.9, s_styl=0.3) |
| assert 0.0 <= result["threat_score"] <= 1.0 |
| assert len(result["explainability"]) == 2 |
|
|
| def test_no_signals(self): |
| result = compute_ensemble() |
| assert result["threat_score"] == 0.0 |
| assert result["explainability"] == [] |
|
|
| def test_watermark_reduces_score(self): |
| without_wm = compute_ensemble(p_ai=0.8, p_ext=0.5) |
| with_wm = compute_ensemble(p_ai=0.8, p_ext=0.5, p_watermark=1.0) |
| assert with_wm["threat_score"] < without_wm["threat_score"] |
|
|
| def test_high_threat_signals(self): |
| result = compute_ensemble( |
| p_ai=1.0, s_perp=1.0, s_embed_cluster=1.0, |
| p_ext=1.0, s_styl=1.0, p_watermark=0.0 |
| ) |
| assert result["threat_score"] > 0.8 |
|
|
| def test_low_threat_signals(self): |
| result = compute_ensemble( |
| p_ai=0.0, s_perp=0.0, s_embed_cluster=0.0, |
| p_ext=0.0, s_styl=0.0, p_watermark=1.0 |
| ) |
| assert result["threat_score"] == 0.0 |
|
|
| def test_explainability_structure(self): |
| result = compute_ensemble(p_ai=0.5, p_ext=0.3) |
| for item in result["explainability"]: |
| assert "signal" in item |
| assert "value" in item |
| assert "weight" in item |
| assert "contribution" in item |
| assert "description" in item |
|
|
|
|
| class TestCalibrateWeights: |
| def test_empty_samples(self): |
| weights = calibrate_weights([]) |
| assert "WEIGHT_AI_DETECT" in weights |
|
|
| def test_with_samples(self): |
| samples = [ |
| {"p_ai": 0.9, "s_perp": 0.5, "p_ext": 0.1, "s_styl": 0.3}, |
| {"p_ai": 0.1, "s_perp": 0.8, "p_ext": 0.9, "s_styl": 0.2}, |
| {"p_ai": 0.5, "s_perp": 0.3, "p_ext": 0.5, "s_styl": 0.7}, |
| ] |
| weights = calibrate_weights(samples) |
| total = sum(weights.values()) |
| assert total > 0 |
| for v in weights.values(): |
| assert v >= 0 |
|
|