@hautajoki/hexagon
v0.1.0
Published
Luau and Roblox test/benchmark runner with exact-version Tessera execution
Maintainers
Readme
Hexagon
Hexagon is a Luau and Roblox test/benchmark runner. One package contains:
- the
hexagonBun CLI; - the dependency-free Luau runtime and native runner;
- a Roblox runner bundled into exact Tessera artifacts on demand;
- TypeScript types for TypeScript-Go-Roblox suites.
It is intentionally a testing tool, not a task runner. Tessera remains responsible for project configuration, builds, saved place versions, credentials, and Open Cloud execution.
Install
During local development in this repository:
{
"devDependencies": {
"@hautajoki/hexagon": "workspace:*"
}
}A packaged consumer installs the release as a normal development dependency and exposes direct scripts:
bun add --dev @hautajoki/hexagon{
"scripts": {
"test": "hexagon test",
"bench": "hexagon bench"
}
}No second Hexagon config file is required.
Native runs require the luau executable. Cloud runs additionally require the
tessera executable at version 0.2.0 or newer and an existing Tessera
project/place configuration.
Hexagon owns the transient <root>/test/hexagon path; add that path to the
project ignore file so an interrupted run cannot surface generated runtime
files as authored changes.
Conventions
*.local.spec.luauand*.local.bench.luauare native-capable and also run in cloud coverage.*.spec.ts,*.bench.ts,*.spec.luau, and*.bench.luaurun in a Roblox Open Cloud artifact.- Suites return or default-export
(t) => { ... }. - Files are discovered in lexical order.
- Correctness tests in benchmark modules always run before timings.
- Empty selections and focused
.onlycases exit nonzero by default.
TypeScript suites import only the API type:
import type { Suite } from "@hautajoki/hexagon";
const suite: Suite = (t) => {
t.test("works", () => {
const resource = acquireResource();
t.cleanup(() => resource.Destroy());
t.expect(resource).toExist();
});
};
export = suite;Every t.cleanup callback runs once in LIFO order, even when the body or
another cleanup fails. afterEach callbacks receive the same all-cleanups
guarantee. Benchmark afterSample also runs when setup or timing fails, and a
cleanup failure is retained alongside the primary failure.
Isolation
File isolation is the default:
- native files run in separate
luauprocesses and therefore separate VMs; - cloud files run in separate Open Cloud executions and therefore separate DataModels.
Cases within one file intentionally share that file's VM/DataModel. Use
t.cleanup for case-owned state. --isolation run is a faster opt-in that
loads all selected files in one VM/DataModel.
For cloud file isolation, Hexagon asks Tessera to build and save once, reads
the exact version from tessera run --json, then invokes every suite against
that same version.
For native execution, Hexagon temporarily materializes its runtime under
<root>/test/hexagon as well. This keeps Luau's relative module resolution
inside the consumer source tree even when the package manager stores Hexagon in
an external cache.
Open Cloud artifact bundling
hexagon test --cloud temporarily materializes its version-matched Roblox
runtime under <root>/test/hexagon, invokes tessera run --fresh, and removes
the generated runtime afterward. The project keeps its normal
tessera.config.ts; no generated suite manifest or second deployment config is
committed.
Co-located suites are compiled by the project's existing source/build recipe,
so the saved test artifact contains both suites and the runner. This includes
native-capable .local.* suites. A custom source router can override the runner
DataModel path with --runner.
This mechanism does not decide whether a project's production build excludes co-located suites. That remains an explicit build/release choice; use a dedicated test artifact or a project build variant when production exclusion is required.
Commands
hexagon test
hexagon bench terrain
hexagon test --cloud
hexagon test --cloud --environment development --place main
hexagon test --cloud --version 1234
hexagon test --cloud --isolation run
hexagon test --jsonFresh exact artifacts are the cloud default. --published is deliberately
named for its weaker mutable-head semantics and is permitted only with shared
run isolation. --allow-focused likewise requires --isolation run, ensuring
that focus is global rather than scoped independently to each file. It is
intended for a deliberate interactive run, not release validation.
