Testing

Discover and run JavaScript, TypeScript, and JVM tests

elide test runs the tests in an Elide project and returns a non-zero exit code when a test fails.

elide test
Discovering and running tests with Elide

JavaScript and TypeScript

Guest tests use the node:test API and are discovered without manifest configuration. Elide recognizes these filename forms:

  • *.test.*
  • *.spec.*
  • *_test.*
  • *_spec.*

Files below test, tests, and __tests__ directories are also treated as tests. Supported guest extensions include JavaScript and TypeScript module variants such as .js, .mjs, .cjs, .ts, .mts, and .cts.

Dependency, build-output, and hidden directories are skipped during automatic discovery.

import test from "node:test";
import assert from "node:assert";

test("adds two values", () => {
  assert.equal(1 + 1, 2);
});

JVM tests

JVM tests run through JUnit and require a test source set declared in elide.pkl. Elide does not discover JVM tests by convention in a project without a manifest.

Select tests

Bare arguments narrow guest discovery to files or directories:

elide test src/api
elide test src/api/client.test.ts

Use -t to match test names:

elide test -t 'parses .+ headers'

For JVM tests, a dotted package name becomes a JUnit package selector. The advanced --select option accepts JUnit selector syntax such as class:com.example.SomeTest.

Useful options

OptionEffect
-t REGEXMatch test or enclosing-suite names.
--bail[=N]Stop after failures; a bare flag means one.
--test-timeout=MSSet the default timeout for each test.
--timeout DURATIONBound the complete Elide invocation.
--onlyRun tests marked .only.
--concurrency=NRun guest files or JVM classes concurrently.
--reporter=junitWrite JUnit-compatible reports.
--reporter=tapWrite TAP 13 to stdout (and under --reporter-outfile).
--reporter-outfile=DIRDirectory to write reports into.

--concurrency=0 is invalid. JavaScript tests run one file at a time by default; JVM tests run one class at a time.

Output and reports

Per-test progress and diagnostics are written to stderr. The final tally is written to stdout. This allows a pipeline to capture them separately:

elide test > summary.txt
elide test 2> progress.txt

Machine-readable reports are written below .dev/reports/tests/<language>/<source-set>/ when a reporter is enabled.

TAP output

--reporter=tap turns stdout into a TAP 13 stream, and nothing else is written to it:

TAP version 13
# start 1: suite A > t1
# out 1: printed from inside a test
ok 1 - suite A > t1
# start 2: broken
not ok 2 - broken
  ---
  message: "expected 1 to equal 2"
  severity: "ERR_ASSERTION"
  ...
1..2

Each test is announced as it starts, carrying the id that every line it writes is tagged with; # out: <text> without an id is output no test owns. Test points are numbered in the order tests settle, 1..N with no gaps, so a point number and a start id name the same test only when tests settle in the order they started — the # start comment, not the number, is what joins the two. A YAML block appears only on a failure that has something to report; its severity carries the runner’s own error code, and is absent when the engine reports none.

Only stdout is framed. Stderr is passed through verbatim, so elide test --reporter=tap 2>&1 is not a TAP stream.

For JVM tests, a line the JUnit launcher prints is attributed only while exactly one test is open. Run classes concurrently — with --concurrency=N above 1, or a project’s own junit-platform.properties — and output that cannot be pinned to one test arrives untagged.

For JavaScript and TypeScript, console.log from inside a test — and from a test file’s top level, once it has imported node:test — is handed to the stream and framed rather than written straight to stdout. Output written before that import lands on stdout raw. Hook output belongs to the test the hook brackets, and t.diagnostic is framed the same way, as # out <id>: <text> rather than a bare # comment.

Coverage

Pass --coverage to collect coverage for the languages participating in the run:

elide test --coverage

Coverage is off unless enabled by the command or manifest. JVM coverage can produce HTML, XML, or CSV reports; JavaScript and TypeScript coverage is written as LCOV. The console prints one combined summary after the run.

Coverage configuration belongs in elide.pkl; see the elide.pkl Reference for the current schema.

Current limits

  • Python test discovery is not available.
  • JVM discovery requires a manifest test source set.
  • node:test snapshots, mock.module, watch mode, programmatic run(), and node:test/reporters are not implemented.

See Node test API for the supported runtime surface.