SciPeerAI-API / tests /test_replication_predictor.py
Abu-Sameer-66
fix: v2.3.4 final version bump
535dd76
Raw
History Blame Contribute Delete
3.94 kB
# 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