Language Support¶
ci-test-gate recognises test files by language. The classifier uses file
extension matching to associate source files with their corresponding tests.
Supported Languages¶
Python¶
Test patterns:
- tests/test_*.py — conventional pytest layout
- test_*.py — flat layout
- *_test.py — unittest convention
| Source | Test |
|---|---|
src/app.py |
tests/test_app.py |
src/utils/helpers.py |
tests/test_helpers.py |
package/module.py |
package/test_module.py |
JavaScript / TypeScript¶
Test patterns:
- *.test.js, *.test.ts — Jest, Vitest
- *.spec.js, *.spec.ts — Angular, older Jasmine
- __tests__/*.js — colocated tests
| Source | Test |
|---|---|
src/app.ts |
src/app.test.ts |
src/components/Button.tsx |
src/components/__tests__/Button.tsx |
lib/utils.js |
lib/utils.spec.js |
Go¶
Test pattern: *_test.go
Go uses a simple convention — test files are in the same package directory as source files.
| Source | Test |
|---|---|
cmd/server.go |
cmd/server_test.go |
pkg/handler/user.go |
pkg/handler/user_test.go |
Rust¶
Test patterns:
- tests/*.rs — integration tests
- src/**/*.rs inline #[cfg(test)] modules
| Source | Test |
|---|---|
src/lib.rs |
tests/integration.rs |
src/handler.rs |
src/handler.rs (inline test mod) |
Mixed-Language Example¶
Monorepo with multiple languages:
# ci-test-gate.yml
languages:
python:
test_patterns: ["tests/test_*.py", "test_*.py"]
javascript:
test_patterns: ["*.test.js", "*.spec.js"]
go:
test_patterns: ["*_test.go"]
rust:
test_patterns: ["tests/*.rs"]
# Override auto-detection per path
overrides:
path: "frontend/**"
language: "javascript"
File Extension Mapping¶
The classifier matches file extensions to ecosystems:
| Extension | Language |
|---|---|
.py |
Python |
.js, .jsx |
JavaScript |
.ts, .tsx |
TypeScript |
.go |
Go |
.rs |
Rust |
.java |
Java |
.kt |
Kotlin |
.rb |
Ruby |
.php |
PHP |
How matching actually works¶
Two implementation notes, because the tables above describe conventions while the code does something simpler and more general.
The match is on the reduced test name, not on a per-language pattern table.
For each test path, test_, _test. and tests/ are stripped, and the result
is substring-matched against each changed path. tests/test_app.py reduces to
app.py, so a change to src/app.py matches. There is no *.test.ts or
*_test.go rule being applied — those conventions are already covered, because
the reduced name of any of those files still contains the source name.
Extension mapping feeds the LLM context, not the heuristic. The
detect_language() table in src/ci_test_gate/context.py maps .py, .js,
.jsx, .ts, .tsx, .rs, .go and .java to a language, picks the majority
language of the diff, and attaches it to the prompt. Every other extension —
including .kt, .rb and .php — is unknown. The heuristic classifier is
language-agnostic and works from paths alone.
The ci-test-gate.yml block above is not read by the current CLI. There is
no --config flag and no config-file loader in src/ci_test_gate/;
configuration is CLI flags and environment variables only — see
Configuration. The block is kept here as the intended shape
for per-language pattern overrides.
Test discovery¶
The local command discovers tests itself, using fixed git pathspecs
regardless of language:
For anything outside those patterns, pass an explicit list with
suggest --test-files.