Spaces:
Sleeping
Sleeping
File size: 3,942 Bytes
535dd76 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # tests/test_replication_predictor.py
#
# Test suite for Replication Predictor (Module 21).
# 10 tests covering ensemble ML prediction, probability bounds,
# verdict generation, flag structure, and edge cases.
# Note: rf_v2.pkl is local-only — tests handle UNKNOWN fallback.
import pytest
from src.scipeerai.modules.replication_predictor import analyze
_VALID_RISK = ("low", "medium", "high", "critical", "UNKNOWN")
def _make_scores(val=0.0):
return {
"score_stat": val,
"score_method": val,
"score_citation": val,
"score_repro": val,
"score_novelty": val,
"score_grim": val,
"score_sprite": val,
"score_granularity": val,
"score_pcurve": val,
"score_effect": val,
"score_retraction": val,
"score_cartel": val,
"score_llm": val,
"score_fraud": val,
"score_temporal": val,
"score_dna": val,
"score_dataprint": val,
"score_peerreview": val,
"score_spectrum": val,
}
def test_high_risk_scores_run():
"""High risk scores — module runs without raising."""
scores = _make_scores(0.9)
r = analyze(scores, text="High risk paper with many fraud signals detected.")
assert r.replication_probability >= 0.0
assert r.fraud_probability >= 0.0
def test_low_risk_scores_run():
"""All clean scores — module runs without raising."""
scores = _make_scores(0.0)
r = analyze(scores, text="Clean paper with no fraud signals detected.")
assert r.replication_probability >= 0.0
assert r.risk_level in _VALID_RISK
def test_replication_probability_bounded():
"""Replication probability always between 0 and 1."""
scores = _make_scores(0.5)
r = analyze(scores, text="Mixed signals paper with moderate risk scores.")
assert 0.0 <= r.replication_probability <= 1.0
def test_fraud_probability_bounded():
"""Fraud probability always between 0 and 1."""
scores = _make_scores(0.5)
r = analyze(scores, text="Mixed signals paper with moderate risk scores.")
assert 0.0 <= r.fraud_probability <= 1.0
def test_probabilities_non_negative():
"""Both probabilities are non-negative in all cases."""
scores = _make_scores(0.3)
r = analyze(scores, text="Paper with moderate statistical risk signals.")
assert r.replication_probability >= 0.0
assert r.fraud_probability >= 0.0
def test_verdict_is_string():
"""Verdict is always a string regardless of model state."""
scores = _make_scores(0.4)
r = analyze(scores, text="Paper under evaluation for replication risk.")
assert isinstance(r.verdict, str)
def test_flag_structure_complete():
"""Every flag has all five required fields."""
scores = _make_scores(0.8)
r = analyze(scores, text="Very high risk paper with extreme fraud signals.")
for flag in r.flags:
assert "flag_type" in flag
assert "severity" in flag
assert "description" in flag
assert "evidence" in flag
assert "suggestion" in flag
def test_model_version_string():
"""Model version is always a non-empty string."""
scores = _make_scores(0.2)
r = analyze(scores, text="Paper with low risk scores across all modules.")
assert isinstance(r.model_version, str)
assert len(r.model_version) > 0
def test_summary_not_empty():
"""Summary always returns a non-empty string."""
scores = _make_scores(0.3)
r = analyze(scores, text="Paper being evaluated for scientific integrity.")
assert isinstance(r.summary, str)
assert len(r.summary) > 10
def test_risk_level_valid():
"""Risk level is always one of the valid values including UNKNOWN."""
scores = _make_scores(0.5)
r = analyze(scores, text="Paper with mixed integrity signals throughout.")
assert r.risk_level in _VALID_RISK |