code_analyze_mcp/
test_detection.rs1use std::path::Path;
7
8pub fn is_test_file(path: &Path) -> bool {
21 for component in path.components() {
23 if let Some("tests" | "test" | "__tests__" | "spec") = component.as_os_str().to_str() {
24 return true;
25 }
26 }
27
28 let file_name = match path.file_name().and_then(|n| n.to_str()) {
30 Some(name) => name,
31 None => return false,
32 };
33
34 if file_name.starts_with("test_") && file_name.ends_with(".rs") {
36 return true;
37 }
38 if file_name.ends_with("_test.rs") {
39 return true;
40 }
41
42 if file_name.starts_with("test_") && file_name.ends_with(".py") {
44 return true;
45 }
46 if file_name.ends_with("_test.py") {
47 return true;
48 }
49
50 if file_name.ends_with("_test.go") {
52 return true;
53 }
54
55 if file_name.starts_with("Test") && file_name.ends_with(".java") {
57 return true;
58 }
59 if file_name.ends_with("Test.java") {
60 return true;
61 }
62
63 if file_name.ends_with(".test.ts") || file_name.ends_with(".test.js") {
65 return true;
66 }
67 if file_name.ends_with(".spec.ts") || file_name.ends_with(".spec.js") {
68 return true;
69 }
70
71 false
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn filename_pattern_detects_test_file() {
80 assert!(is_test_file(Path::new("test_utils.rs")));
81 assert!(is_test_file(Path::new("utils_test.rs")));
82 }
83
84 #[test]
85 fn filename_pattern_rejects_production_file() {
86 assert!(!is_test_file(Path::new("utils.rs")));
87 assert!(!is_test_file(Path::new("main.rs")));
88 }
89
90 #[test]
91 fn directory_pattern_detects_test_file() {
92 assert!(is_test_file(Path::new("tests/utils.rs")));
93 }
94
95 #[test]
96 fn directory_pattern_detects_nested_test_file() {
97 assert!(is_test_file(Path::new("src/tests/utils.rs")));
98 assert!(!is_test_file(Path::new("src/utils.rs")));
99 }
100}