The test scaffold command generates test boilerplate from rule declarations in an Allium spec. The output language and test runner depend on a framework configured in allium.config.json.
Add a scaffold key to your project's allium.config.json:
{
"scaffold": {
"framework": "vitest"
}
}Without this key the command will prompt you to configure one.
| ID | Language | Test runner |
|---|---|---|
node:test |
TypeScript | Node.js built-in test runner |
jest |
TypeScript | Jest (globals, no import needed) |
vitest |
TypeScript | Vitest |
pytest |
Python | pytest |
junit5 |
Java | JUnit 5 |
clojure.test |
Clojure | clojure.test |
The output is a scaffold, not a complete test file. You will still need to import the module under test and fill in assertions. JUnit 5 output omits the enclosing class declaration since the class name and package depend on your project structure.
Framework templates live in extensions/allium/src/language-tools/test-scaffold-frameworks.ts. Each framework implements the ScaffoldFramework interface and is registered as an entry in the frameworks Map. The Map key is the string users set in allium.config.json and must match the id field.
interface ScaffoldFramework {
id: string; // must match the Map key
languageId: string; // VS Code language ID for the opened document
header: string[]; // import lines emitted once at the top of the file
testOpen: (name: string) => string; // opening line(s) of each test
testClose: string; // closing line of each test (empty string if none)
comment: (text: string) => string; // single-line comment syntax
placeholder: string; // default assertion or TODO marker
indent: string; // indentation within a test body
}If the spec contains no rule declarations, the generator returns an empty string and the command shows a "no rules found" message.
Otherwise the output is assembled in order:
- The
headerlines (imports, require statements), followed by a blank line. - For each rule declaration:
testOpen(moduleName + " / " + ruleName)to open the test. If this returns a string containing\n(as JUnit 5 does for the@Testannotation), the generator splits it into separate lines.- An indented comment for each
when,requiresandensuresclause, viacomment(). - The
placeholderline, indented. testClose, if non-empty.- A trailing blank line.
The full test name passed to testOpen is "moduleName / RuleName". Frameworks that use the name as a string (node:test, jest, vitest) can pass it through directly. Frameworks that need a valid identifier must sanitise it.
Two helpers are exported from the frameworks module:
toSnakeCase(s)splits camelCase boundaries, replaces non-alphanumeric characters with underscores, trims leading/trailing underscores and lowercases. Suitable for Python and Java identifiers.toKebabCase(s)does the same but joins with hyphens. Suitable for Clojure symbols.
[
"rspec",
{
id: "rspec",
languageId: "ruby",
header: [],
testOpen: (name) => `it "${name}" do`,
testClose: "end",
comment: (text) => `# ${text}`,
placeholder: "expect(true).to eq(true)",
indent: " ",
},
],RSpec uses string-based test names, so testOpen passes the name through without sanitisation. A framework that needs an identifier (like pytest's def test_...) would call toSnakeCase(name) instead.
After adding the entry to the frameworks Map:
- Update the
frameworkIds()assertion inextensions/allium/test/test-scaffold.test.tsto include"rspec"in the expected array. - Add a test case that verifies the output shape.
- Run
npm run buildin bothextensions/alliumandpackages/allium-lsp. - Run
npm testfrom the workspace root.
- No structural wrapping. The interface produces a flat sequence of test functions. Frameworks that require enclosing structure (a JUnit class, a Go test file with
packagedeclaration) need the user to add the wrapper. If this becomes a common need, the interface could grow optionalfileOpen/fileClosecallbacks. - Name collisions. If two rules produce the same identifier after sanitisation (e.g.
CloseTicketandClose_Ticketboth becomingclose_ticket), the scaffold will contain duplicate function names. This is rare in practice.