jigUser Guide
Overview
Jig is a better Fantom test runner.
Jig wraps fant with output you can scan: results grouped by pod and test class, a live status bar pinned to the bottom of the terminal, and failures printed with only the output and stack frames that matter.
acme AddrTest [ 7/ 7] pass (3ms) ScheduleTest [ 6/ 6] pass (37ms) UserTest [ 5/ 5] pass (2ms) SyncTest [ 3/ 3] pass (6.0sec) CsvReaderTest [10/10] pass (10ms) InvoiceTest [12/12] pass (1278ms) ─────────────────────────── ✓ 43 passed (7.4sec) acmeWeb SessionTest [ 8/ 8] pass (405ms) RenderTest [16/16] pass (3475ms) AssetTest [ 4/ 4] pass (55ms) RouteTest [22/22] pass (9ms) ─────────────────────────── ✓ 50 passed (3973ms) ✓ All 93 tests passed [601 verifies] in 11.5sec
Install
Install from Eggbox with fanr:
fanr install jig
If your etc/fanr/config.props doesn't default to Eggbox, pass the repo:
fanr install -r https://eggbox.fantomfactory.org/fanr/ jig
Run this from outside any workenv (a directory with no fan.props above it). fanr installs into the current env's lib/fan/, so outside a workenv jig lands in your Fantom home and fan jig works from any workenv.
To build from source instead, copy the pod into your Fantom home (fan -version prints the fan.home path):
fan src/jig/build.fan cp lib/fan/jig.pod <fan.home>/lib/fan/
Run as jig
On macOS or Linux, save this script as jig in the bin/ directory of the Fantom install you want it to use, next to fan and fant (fan -version prints the fan.home path), and make it executable with chmod +x:
#!/bin/sh
. "${0%/*}/fanlaunch"
fanlaunch Fan jig "$@"Now jig acme works the same as fan jig acme. Like fant and fanr, it runs with the Fantom install it lives in, not whichever fan is first on your PATH. Don't symlink it elsewhere, since it finds fanlaunch next to itself.
Usage
jig [options] <targets>*
Targets use the same syntax as fant:
fan jig acme # all tests in pod fan jig acme::FooTest # all tests in a type fan jig acme::FooTest.testBar # a single test method fan jig -w # all pods in workDir lib/fan/
Options:
-w,--work: test all pods in your workenv'slib/fan/-q,--quiet: only print failures, status bar, and summary-es: test new ECMA JavaScript environment (passthrough)-js: test legacy JavaScript environment (passthrough)
Exit code is 0 if all tests pass, 1 otherwise.
-w vs fant -all
fant -all runs every pod the env can resolve, including Fantom core and any fan.props path dependencies. jig -w only runs pods built into your workenv's own lib/fan/, and refuses to run outside a workenv.
Output
Default prints one line per test class, grouped by pod:
[passed/total]counts, with columns aligned across all podspass/failwith elapsed time for the class (4900msunder 5sec,7.2secunder a minute, then1min 2sec)- A
FAIL: <method>line under the class for each failed test - A summary line after each pod when the run covers more than one pod
Output from passing tests is hidden.
Quiet (-q) prints a FAIL: line with the full qualified name as each test fails, and nothing for passing tests.
Both modes end with the details for every failure together, so you don't have to hunt through scrollback: anything the test printed (prefixed with |) and the stack trace with test harness frames (reflection, TestRunner, verify internals) removed. Then a one-line summary, plus one line per failure showing how many tests in that class failed.
Status bar. When stdout is a terminal, a status bar on the bottom line shows percent complete, tests run, pass/fail counts, total elapsed time, and the current pod with its test progress, so you know where you are after the pod header scrolls away. In default mode the class currently running sits above it with live counts and a timer for the running method. Colors and the status bar are disabled when output is piped, CI is set, or TERM=dumb.
Platform Support
Jig is built for macOS and Linux terminals. It runs on Windows, but the terminal output has rough edges:
- Colors and status bar. Jig uses ANSI escape codes, which Windows Terminal supports but the legacy console does not. Use Windows Terminal, or set
TERM=dumbto get plain output. - Symbols.
✓ ✗ █ ░need a UTF-8 console. Runchcp 65001first if they show as garbled characters. - Terminal width. Width detection uses
stty, which Windows lacks, so jig assumes 80 columns. SetCOLUMNSto your window width if long lines wrap.
Build Scripts
BuildPod runs tests with fant in its test target, which full also calls. Override test to use jig instead:
class Build : BuildPod
{
...
@Target { help = "Run the pod unit tests via jig" }
override Void test()
{
fan := devHomeDir + (Env.cur.os == "win32" ? `bin/fan.bat` : `bin/fan`)
Exec(this, [fan.osPath, "jig", podName]).run
}
}Failing tests fail the build. For a BuildGroup, override full to clean and compile every pod first, then test them all in a single jig run:
class Build : BuildGroup
{
...
@Target { help = "Clean and compile all pods, then test all via jig" }
Void full()
{
runOnChildren("clean")
runOnChildren("compile")
fan := devHomeDir + (Env.cur.os == "win32" ? `bin/fan.bat` : `bin/fan`)
Exec(this, [fan.osPath, "jig"].addAll(podNames(this))).run
}
** Pod names of all BuildPod scripts in this group (recursive)
private Str[] podNames(BuildScript s)
{
if (s is BuildPod) return [((BuildPod)s).podName]
if (s is BuildGroup) return ((BuildGroup)s).children.map |c| { podNames(c) }.flatten
return Str[,]
}
}Exec captures jig's output, so in build scripts jig prints plain output without colors or the status bar.
How it Works
Jig resolves targets up front (so typos fail fast and the status bar knows the total), spawns a single fant process, and parses its output as tests run.