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