pub mod analyzer;
pub mod assertion_detector;
pub mod complexity_scorer;
pub mod flaky_detector;
pub mod framework_detector;
pub mod test_classifier;
use crate::core::{DebtItem, DebtType, Priority};
use std::path::Path;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RustTestFramework {
Std,
Criterion,
Proptest,
Quickcheck,
Rstest,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RustTestType {
UnitTest,
IntegrationTest,
BenchmarkTest,
PropertyTest,
DocTest,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RustAssertionType {
Assert,
AssertEq,
AssertNe,
Matches,
ShouldPanic,
ResultOk,
Custom(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RustFlakinessType {
TimingDependency,
RandomValue,
ExternalDependency,
FileSystemDependency,
NetworkDependency,
ThreadingIssue,
HashOrdering,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RustTestSeverity {
Critical,
High,
Medium,
Low,
}
#[derive(Debug, Clone)]
pub struct RustTestQualityIssue {
pub issue_type: RustTestIssueType,
pub test_name: String,
pub line: usize,
pub severity: RustTestSeverity,
pub confidence: f32,
pub explanation: String,
pub suggestion: String,
}
#[derive(Debug, Clone, PartialEq)]
pub enum RustTestIssueType {
NoAssertions,
TooComplex(u32),
FlakyPattern(RustFlakinessType),
ExcessiveMocking(usize),
IsolationIssue,
TestsTooMuch,
SlowTest,
}
pub fn convert_rust_test_issue_to_debt_item(issue: RustTestQualityIssue, path: &Path) -> DebtItem {
let (priority, message, context, debt_type) = match issue.issue_type {
RustTestIssueType::NoAssertions => (
Priority::High,
format!("Test '{}' has no assertions", issue.test_name),
Some(format!(
"{}\n\nSuggestion: {}",
issue.explanation, issue.suggestion
)),
DebtType::TestQuality {
issue_type: Some("no_assertions".to_string()),
},
),
RustTestIssueType::TooComplex(score) => (
Priority::Medium,
format!(
"Test '{}' is overly complex (score: {})",
issue.test_name, score
),
Some(format!(
"{}\n\nSuggestion: {}",
issue.explanation, issue.suggestion
)),
DebtType::TestComplexity {
cyclomatic: score,
cognitive: score,
},
),
RustTestIssueType::FlakyPattern(ref flakiness_type) => (
Priority::High,
format!(
"Test '{}' has flaky pattern: {:?}",
issue.test_name, flakiness_type
),
Some(format!(
"{}\n\nSuggestion: {}",
issue.explanation, issue.suggestion
)),
DebtType::TestQuality {
issue_type: Some(format!("flaky_{:?}", flakiness_type)),
},
),
RustTestIssueType::ExcessiveMocking(count) => (
Priority::Medium,
format!(
"Test '{}' has excessive mocking ({} mocks)",
issue.test_name, count
),
Some(format!(
"{}\n\nSuggestion: {}",
issue.explanation, issue.suggestion
)),
DebtType::TestComplexity {
cyclomatic: count as u32,
cognitive: count as u32,
},
),
RustTestIssueType::IsolationIssue => (
Priority::High,
format!("Test '{}' has isolation issues", issue.test_name),
Some(format!(
"{}\n\nSuggestion: {}",
issue.explanation, issue.suggestion
)),
DebtType::TestQuality {
issue_type: Some("isolation_issue".to_string()),
},
),
RustTestIssueType::TestsTooMuch => (
Priority::Medium,
format!("Test '{}' tests too many concerns", issue.test_name),
Some(format!(
"{}\n\nSuggestion: {}",
issue.explanation, issue.suggestion
)),
DebtType::TestQuality {
issue_type: Some("tests_too_much".to_string()),
},
),
RustTestIssueType::SlowTest => (
Priority::Low,
format!("Test '{}' may be slow", issue.test_name),
Some(format!(
"{}\n\nSuggestion: {}",
issue.explanation, issue.suggestion
)),
DebtType::TestComplexity {
cyclomatic: 0,
cognitive: 0,
},
),
};
DebtItem {
id: format!("rust-test-{}-{}", path.display(), issue.line),
debt_type,
priority,
file: path.to_path_buf(),
line: issue.line,
column: None,
message,
context,
}
}