VS Code extension to quickly switch between source and test files. Works out of the box with common conventions and is fully configurable for custom project structures.
| Shortcut | Command | Description |
|---|---|---|
Cmd+Shift+T / Ctrl+Shift+T |
FLIP: Flip to Test/Source | Toggle between unit test and source file using deterministic candidate matching |
Cmd+Shift+A / Ctrl+Shift+A |
FLIP: Flip to Related File | Smart search with scoring — finds related files (e.g. acceptance tests) using template matching, fuzzy glob search, and multi-signal scoring |
Alt+Shift+T |
FLIP: Open Test/Source Side by Side | Same as Flip to Test/Source but opens in a split editor |
| — | FLIP: Create Test File | Creates a new test file with boilerplate for the current source file |
Generates exact candidate paths by combining configured path mappings with test file prefixes/suffixes. Tries each candidate in order, falling back to a workspace-wide glob search by filename if no exact path exists. Fast and predictable.
Uses a multi-phase pipeline to find related files:
- Template matching — applies
flip.relatedMappingstemplates to resolve exact candidate paths - Glob search — searches within configured
searchPathsfor broader matches - Fuzzy keyword search — extracts keywords from the filename and searches for similar files
- Scoring — ranks all results using six signals:
- Structural path mirroring (parallel directory trees)
- LCS-based path segment similarity
- Core name match (stripped of test affixes)
- Extension affinity (language-family compatibility)
- Direction indicators (test vs. source directory)
- Keyword word overlap
If the top result is clearly best (score gap > 20), it opens automatically. Otherwise a QuickPick shows the ranked candidates.
test_/ut_prefix —src/modules/X/foo.cpp↔test/modules/X/test_foo.cpp_testsuffix —foo.go↔foo_test.go.test./.spec.suffix —app.ts↔app.test.ts- Java
Testprefix/suffix —Foo.java↔TestFoo.java/FooTest.java - Directory mirroring —
src/↔test/,src/main/java↔src/test/java,lib/↔test/, etc.
All settings are under flip.* in VS Code settings.
Directory segment pairs for source ↔ test mirroring. Order matters — first match wins.
Filename conventions that identify test files:
"flip.testFilePrefixes": ["test_", "ut_"],
"flip.testFileSuffixes": ["_test", ".test", ".spec"]Enable TestFoo / FooTest detection (default: true).
Template-based mappings for related files (e.g. acceptance tests, e2e tests) used by Cmd+Shift+A. Each mapping has:
| Field | Type | Description |
|---|---|---|
source |
string |
Source path template with {name} (one segment) or {path} (multi-segment) placeholders |
test |
string |
Test path template using the same placeholders |
filePrefix |
string |
Filename prefix for related files (e.g. at_, e2e_) |
searchPaths |
string[] |
Glob patterns that scope the fuzzy search to specific directories |
"flip.relatedMappings": [
{
"source": "components/{comp}/src/modules/{path}",
"test": "test/at_components/{comp}/{path}",
"filePrefix": "at_",
"searchPaths": ["**/test/at_components/**"]
},
{
"source": "components/{comp}/src",
"test": "test/at_components/{comp}",
"filePrefix": "at_",
"searchPaths": ["**/test/at_components/**"]
}
]{
"flip.pathMappings": [{ "source": "lib", "test": "spec" }],
"flip.testFilePrefixes": [],
"flip.testFileSuffixes": ["_spec"],
"flip.javaStyle": false
}{
"flip.pathMappings": [{ "source": "src", "test": "tests" }],
"flip.testFilePrefixes": ["test_"],
"flip.testFileSuffixes": [],
"flip.javaStyle": false
}The simplest way to use Cmd+Shift+A is to provide only searchPaths — no templates needed. The fuzzy keyword search + scoring will find related files within those directories:
{
"flip.relatedMappings": [
{
"searchPaths": ["**/integration/tests/**"]
}
]
}This makes Cmd+Shift+A search for related files only inside integration/tests/, using filename keywords and scoring to find the best match.
For more precise matching, add source/test templates and a filePrefix. This enables exact candidate resolution in addition to fuzzy search:
{
"flip.relatedMappings": [
{
"source": "src/{path}",
"test": "integration/tests/{path}",
"filePrefix": "test_",
"searchPaths": ["**/integration/tests/**"]
}
]
}Custom boilerplate templates used when creating new test files. Each entry maps file extensions to a template string. If no template matches, built-in defaults are used.
| Placeholder | Expands to |
|---|---|
{name} |
Source filename without extension (e.g. parser) |
{Name} |
Capitalized source name (e.g. Parser) |
{className} |
Test filename without extension (e.g. test_parser) |
{package} |
Parent directory name (e.g. utils) |
Use \n for newlines in the template string.
"flip.testTemplates": [
{
"extensions": [".cpp", ".h"],
"template": "#include \"{name}.h\"\n\nTEST({Name}, ShouldWork) {\n\n}\n"
},
{
"extensions": [".ts", ".tsx"],
"template": "import { {name} } from './{name}';\n\ndescribe('{name}', () => {\n it('should work', () => {\n\n });\n});\n"
},
{
"extensions": [".py"],
"template": "import pytest\nfrom {package}.{name} import *\n\n\ndef test_{name}():\n pass\n"
}
]With this configuration, Cmd+Shift+A first tries exact template matching, then falls back to fuzzy search scoped to integration/tests/. For example:
src/services/auth.ts→ findsintegration/tests/services/test_auth.ts
npm install && npm run compile
npm run packageThen install via Extensions → Install from VSIX…
npm run watch # compile on change
npm test # run unit testsPress F5 in VS Code to launch an Extension Development Host.
