Check if a file path looks like a test file (language-agnostic). */
| 59 | |
| 60 | /* Check if a file path looks like a test file (language-agnostic). */ |
| 61 | bool cbm_is_test_path(const char *path) { |
| 62 | if (!path) { |
| 63 | return false; |
| 64 | } |
| 65 | const char *base = strrchr(path, '/'); |
| 66 | base = base ? base + SKIP_ONE : path; |
| 67 | size_t len = strlen(path); |
| 68 | |
| 69 | /* Prefix-based: Python test_*.py */ |
| 70 | if (strncmp(base, "test_", SLEN("test_")) == 0) { |
| 71 | return true; |
| 72 | } |
| 73 | |
| 74 | /* Suffix-based: _test.<ext> pattern (Go, Python, Rust, C++, Lua) */ |
| 75 | if (str_ends_with(path, len, "_test.go") || str_ends_with(path, len, "_test.py") || |
| 76 | str_ends_with(path, len, "_test.rs") || str_ends_with(path, len, "_test.cpp") || |
| 77 | str_ends_with(path, len, "_test.lua")) { |
| 78 | return true; |
| 79 | } |
| 80 | |
| 81 | /* .test.<ext> / .spec.<ext> pattern (JS/TS/TSX) */ |
| 82 | if (strstr(path, ".test.ts") || strstr(path, ".spec.ts") || strstr(path, ".test.js") || |
| 83 | strstr(path, ".spec.js") || strstr(path, ".test.tsx") || strstr(path, ".spec.tsx")) { |
| 84 | return true; |
| 85 | } |
| 86 | |
| 87 | /* Name ends with "Test" or "Spec" before extension (Java, Kotlin, C#, PHP, Scala) */ |
| 88 | if (str_ends_with(path, len, "Test.java") || str_ends_with(path, len, "Test.kt") || |
| 89 | str_ends_with(path, len, "Test.cs") || str_ends_with(path, len, "Test.php") || |
| 90 | str_ends_with(path, len, "Spec.scala")) { |
| 91 | return true; |
| 92 | } |
| 93 | |
| 94 | /* Directory-based: __tests__/, tests/, test/, spec/ */ |
| 95 | if (strstr(path, "__tests__/") || strstr(path, "/tests/") || strstr(path, "/test/") || |
| 96 | strstr(path, "/spec/")) { |
| 97 | return true; |
| 98 | } |
| 99 | /* Also match if path STARTS with these directories */ |
| 100 | if (strncmp(path, "tests/", SLEN("tests/")) == 0 || |
| 101 | strncmp(path, "test/", SLEN("test/")) == 0 || strncmp(path, "spec/", SLEN("spec/")) == 0 || |
| 102 | strncmp(path, "__tests__/", SLEN("__tests__/")) == 0) { |
| 103 | return true; |
| 104 | } |
| 105 | |
| 106 | /* Ruby: _spec.rb suffix */ |
| 107 | if (str_ends_with(path, len, "_spec.rb")) { |
| 108 | return true; |
| 109 | } |
| 110 | |
| 111 | return false; |
| 112 | } |
| 113 | |
| 114 | /* Check if a function name looks like a test function (language-agnostic). */ |
| 115 | bool cbm_is_test_func_name(const char *name) { |
no test coverage detected