Running
bitti run and its flags: which scenarios run, and in which browsers and apps.
bitti run [<file.bt|file.feature|dir>...] [--base-url <url>] [--var k=v] [--grep <text>] [--grep-invert <text>]
[--tag <tag|expression>] [--last-failed] [--max-failures <n>|-x] [--forbid-only|--allow-only]
[--workers <n|auto>|-j <n>] [--isolation context|browser] [--retries <n>] [--fail-on-flaky] [--shard <i/n>]
[--repeat <n>] [--shuffle [<seed>]] [--slowmo <ms>]
[--reporter console|jsonl|github] [--junit <file>] [--cucumber <file>] [--allure <dir>] [--html <file>] [--json]
[--timeout-ms <ms>] [--wait-ms <ms>] [--headed] [--chromium <path>] [--engine chrome|lightpanda]
[--electron <app> [--electron-arg <arg>]...] [--attach <port|ws://…>]
[--secrets <file>] [--evidence <dir>] [--pause-on-failure] [--trace on-failure|all] [--video on-failure|all] [--update-snapshots]
[--compare-report html,json,rows|none] [--config <file>] [--env <name>]
bitti lint [<file.bt|file.feature|dir>...]
bitti list [<file.bt|file.feature|dir>...]
bitti trace <dir> [<line>]
bitti fix [<file>:<line>] [--use <n>] [--all [--min <p>]]
bitti navigera <command…>
bitti from-session <name> [--scenario <name>] [--out <file.bt>]
bitti record <url> [--out <file.bt>] [--scenario <name>] [--headless] [--for <seconds>]
bitti record --extend <file.bt> [--scenario <name>] [--base-url <url>] [--secrets <file>]
bitti mcp [--headed] [--chromium <path>]
bitti skill # the agent skill (what an agent reads to write tests)
bitti <command> --help # that command's usage and options
bitti --version
--base-url falls back to base in the file, then BITTI_BASE_URL.
--workers is auto unless given: half the CPUs, at most 8, and never
more than there are scenarios. --workers 1 runs them one at a time.
Picking what runs
--tag smokeruns the scenarios tagged@smoke; a tag expression picks by several, as Cucumber writes them:--tag "smoke and not slow",--tag "(checkout or cart) and not wip". Repeated, any of them.--grep-invert <text>leaves out the names that contain it.- Some tags say how a scenario runs:
@skipand@fixmearen’t run and are reported as skipped (SKIP, JUnit<skipped/>, Allureskipped);@slowgives each check three times its time;@serial(or@exclusive) runs the scenario while no other one runs, for one that changes what the others read (an app setting, a shared account): the others run in parallel first, then each@serialone alone;@onlyruns only the scenarios that have it, a focus while working on one. It is an error with--forbid-only, which is on by itself under CI (CIset), so a focus left in by mistake doesn’t pass a build on a few scenarios (--allow-onlyruns just those anyway). --max-failures <n>starts no scenario once n have failed (-x: at the first), and says how many were not run; the run fails.--last-failed(--lf) runs only the scenarios that failed in the last run in this directory (.bitti/last-run.json). With none, it says so and exits 0.--scenario-timeout-ms <ms>(scenario_timeout_msinbitti.toml) is the most one scenario’s steps may take: no step starts once it is up, and a step’s wait (anexpect, aretry, anhttporexec, its own--timeout-mstoo) stops there, the failure saying so.@slowtriples it. Off by default.--global-timeout-ms <ms>(global_timeout_ms) does the same for the whole run: no scenario starts after it, those running stop there, and the run fails with the count of scenarios it never ran.--slowmo <ms>waits that long before each step that acts on the page (goto,click,fill…), to follow a--headedrun by eye; checks andhttpsteps aren’t slowed.
Browsers and apps
- A click that opens a tab or a popup (
target=_blank,window.open) moves the scenario to it, as navigera does: the next steps read and act there.tab-select 0goes back to the first tab;tab-closecloses the one you’re on. - Every scenario starts in a fresh browser context (navigera
reset --all: no cookies, storage, tabs, routes, init scripts,setemulation or dialog answer from the scenario before), in about 40 ms instead of a new browser’s few hundred.--workers nruns n at once, each in a browser context of one shared browser (about 40% less memory at 4 workers than a browser each;--isolation browsergives each its own). The longest start first (by.bitti/timings.json, which each run updates; the first run goes in file order). --engine lightpanda(orengine = "lightpanda"in a profile, orNAVIGERA_ENGINE=lightpanda) runs on Lightpanda ($LIGHTPANDA_BINorlightpandaon the PATH), a new Lightpanda for each scenario (it has one context per process): less memory, no layout. It is a smoke tier, not a replacement: hover-revealed elements, new tabs, screenshots andaxpixels need Chrome. On the 40-scenario suite’s 25 site scenarios it passes 22, and is not faster: 22 s against Chrome’s 11 s at one worker (half of it the three failures’ waits).--electron <app>(orelectron = "./app"andelectron_args = [...]inbitti.toml) tests an Electron desktop app instead of a web page: the scenarios drive its windows as tabs, through navigera’sstart --electron.<app>is the app’s directory or main script (the Electron in itsnode_modulesruns it), a packaged app’s executable or a macOS.appbundle. Each scenario gets a fresh app, so none sees what the one before left in its storage, and they run one at a time (two copies of an app would share its user data):--workersbecomes 1. A window the app opens itself (Settings, a second document) becomes the scenario’s tab, and one that closes itself hands back to the one before.expect js --main "<code>"checks the app’s main process (a function gets theelectronmodule:({ app }) => app.getName()), andeval --mainruns code there as a step. On a Linux CI machine, run underxvfb-run. The example:tests/fixtures/electron, run in CI on Linux, macOS and Windows against navigera’s fixture app.--attach <port|ws://…>(orattach = "9222"inbitti.toml) runs against a browser or an Electron app that is already running with a DevTools port: the build a developer has open (npm start -- --remote-debugging-port=9222), or a Chrome they started. In an app, the scenarios run one after the other in the one app, each going on where the one before left it, and the app keeps running after the run. In a browser, each scenario gets a clean context of its own. One worker. The example:tests/fixtures/electron-attached.
Made from docs/running.md.