#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
use crate::services::popper_score::{
AnalysisStatus, PopperAnalysis, PopperCategoryScore, PopperCategoryScores, PopperGrade,
PopperMetadata, PopperRecommendation, PopperSubScore, RecommendationPriority,
};
use tempfile::TempDir;
fn create_test_score_passed() -> PopperScore {
let mut categories = PopperCategoryScores::default();
categories.falsifiability =
PopperCategoryScore::new("Falsifiability & Testability", 20.0, 25.0);
categories.falsifiability.add_sub_score(PopperSubScore::new(
"A1",
"Test Coverage",
8.0,
10.0,
"Unit test coverage",
));
categories.falsifiability.add_sub_score(PopperSubScore::new(
"A2",
"Claims",
12.0,
15.0,
"Testable claims",
));
categories.reproducibility =
PopperCategoryScore::new("Reproducibility Infrastructure", 18.0, 25.0);
categories.transparency = PopperCategoryScore::new("Transparency & Openness", 15.0, 20.0);
categories.statistical_rigor = PopperCategoryScore::new("Statistical Rigor", 10.0, 15.0);
categories.historical_integrity =
PopperCategoryScore::new("Historical Integrity", 7.0, 10.0);
let recommendations = vec![
PopperRecommendation::new(
"Testing",
"Add mutation testing",
RecommendationPriority::High,
5.0,
)
.with_command("cargo mutants"),
PopperRecommendation::new(
"Documentation",
"Improve README",
RecommendationPriority::Medium,
2.0,
),
PopperRecommendation::new(
"Infrastructure",
"Add CI pipeline",
RecommendationPriority::Critical,
8.0,
),
PopperRecommendation::new(
"Testing",
"Add benchmarks",
RecommendationPriority::Low,
1.0,
),
];
PopperScore {
raw_score: 70.0,
max_available: 95.0,
normalized_score: 73.7,
grade: PopperGrade::B,
gateway_passed: true,
categories,
recommendations,
metadata: PopperMetadata::new("test-project".to_string()),
analysis: PopperAnalysis {
falsifiability_status: AnalysisStatus::Pass,
reproducibility_status: AnalysisStatus::Partial,
scrutiny_status: AnalysisStatus::Partial,
methodology_status: AnalysisStatus::Pass,
validation_status: AnalysisStatus::Fail,
verdict: "Good scientific practices with room for improvement.".to_string(),
},
}
}
fn create_test_score_failed() -> PopperScore {
let mut categories = PopperCategoryScores::default();
categories.falsifiability =
PopperCategoryScore::new("Falsifiability & Testability", 10.0, 25.0);
categories.reproducibility =
PopperCategoryScore::new("Reproducibility Infrastructure", 5.0, 25.0);
categories.transparency = PopperCategoryScore::new("Transparency & Openness", 5.0, 20.0);
categories.statistical_rigor = PopperCategoryScore::new("Statistical Rigor", 3.0, 15.0);
categories.historical_integrity =
PopperCategoryScore::new("Historical Integrity", 2.0, 10.0);
PopperScore {
raw_score: 0.0,
max_available: 95.0,
normalized_score: 0.0,
grade: PopperGrade::InsufficientFalsifiability,
gateway_passed: false,
categories,
recommendations: vec![PopperRecommendation::new(
"Falsifiability",
"Add testable claims",
RecommendationPriority::Critical,
25.0,
)],
metadata: PopperMetadata::new("failing-project".to_string()),
analysis: PopperAnalysis {
falsifiability_status: AnalysisStatus::Fail,
reproducibility_status: AnalysisStatus::Fail,
scrutiny_status: AnalysisStatus::Fail,
methodology_status: AnalysisStatus::Fail,
validation_status: AnalysisStatus::Fail,
verdict: "Gateway failed - insufficient falsifiability.".to_string(),
},
}
}
#[tokio::test]
async fn test_handler_invalid_path() {
let result = handle_popper_score(
Path::new("/nonexistent/path"),
&RepoScoreOutputFormat::Text,
false,
false,
None,
)
.await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("not found"));
}
#[tokio::test]
async fn test_handler_not_a_directory() {
let temp = TempDir::new().unwrap();
let file_path = temp.path().join("file.txt");
std::fs::write(&file_path, "not a directory").unwrap();
let result =
handle_popper_score(&file_path, &RepoScoreOutputFormat::Text, false, false, None).await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("not a directory"));
}
#[tokio::test]
async fn test_handler_empty_project() {
let temp = TempDir::new().unwrap();
let result = handle_popper_score(
temp.path(),
&RepoScoreOutputFormat::Text,
false,
false,
None,
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handler_json_output() {
let temp = TempDir::new().unwrap();
std::fs::write(
temp.path().join("README.md"),
"# Test\n\nSuccess criteria: Tests pass.",
)
.unwrap();
let result = handle_popper_score(
temp.path(),
&RepoScoreOutputFormat::Json,
false,
false,
None,
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handler_markdown_output() {
let temp = TempDir::new().unwrap();
std::fs::write(temp.path().join("README.md"), "# Test Project").unwrap();
let result = handle_popper_score(
temp.path(),
&RepoScoreOutputFormat::Markdown,
false,
false,
None,
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handler_yaml_output() {
let temp = TempDir::new().unwrap();
std::fs::write(temp.path().join("README.md"), "# Test Project").unwrap();
let result = handle_popper_score(
temp.path(),
&RepoScoreOutputFormat::Yaml,
false,
false,
None,
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handler_verbose_output() {
let temp = TempDir::new().unwrap();
std::fs::write(temp.path().join("README.md"), "# Test").unwrap();
let result = handle_popper_score(
temp.path(),
&RepoScoreOutputFormat::Text,
true, false,
None,
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handler_failures_only_output() {
let temp = TempDir::new().unwrap();
std::fs::write(temp.path().join("README.md"), "# Test").unwrap();
let result = handle_popper_score(
temp.path(),
&RepoScoreOutputFormat::Text,
false,
true, None,
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handler_output_to_file() {
let temp = TempDir::new().unwrap();
std::fs::write(temp.path().join("README.md"), "# Test").unwrap();
let output_path = temp.path().join("score.txt");
let result = handle_popper_score(
temp.path(),
&RepoScoreOutputFormat::Text,
false,
false,
Some(&output_path),
)
.await;
assert!(result.is_ok());
assert!(output_path.exists());
}
include!("popper_score_tests_format.rs");
}