{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreifxj4lcdx2xktjndsmisqojdo4p62lxf53h57brf6nybz6imf7zqm",
"uri": "at://did:plc:46ti67tc37qcmwp2vaynk6fq/app.bsky.feed.post/3mkwwq23fjcg2"
},
"path": "/inquest-intro.html",
"publishedAt": "2026-05-03T10:21:06.136Z",
"site": "https://www.jelmer.uk",
"tags": [
"testrepository",
"subunit",
"Inquest",
"jelmer/inquest"
],
"textContent": "## testrepository\n\nFor a long time I’ve used Robert Collins’ testrepository (`testr`) to run tests in many of the projects I work on. It’s a small, focused tool built around a simple idea: decouple the _running_ of tests from the _recording_ and _querying_ of their results.\n\nThe way it works is straightforward. A test runner emits a subunit stream — a compact binary protocol for test results — and testrepository stores those streams in a per-project `.testrepository/` directory. Once results are in the repository, you can ask questions like “which tests failed in the last run?”, “re-run only the failures”, “what are the slowest tests?”, or “what changed between this run and the previous one?”.\n\nThe killer feature, for me, has always been the failing-test loop. When a big test suite breaks, you don’t want to re-run the whole thing after every fix — you want to iterate on just the failures, and only re-run the full suite once they’re all green. testrepository made that workflow ergonomic long before most language-specific test runners had anything comparable, and many of them still don’t have a good answer for it.\n\ntestrepository has served me well for over a decade, but it has been largely unmaintained for a while, and I had some ideas of improvements that I wanted to try out. So I wrote a Rust port, which has since grown a number of features of its own.\n\n## Inquest\n\nInquest is a Rust port of testrepository that has since grown a number of features of its own. The binary is called `inq`.\n\n## Goals\n\nThe goals are deliberately modest:\n\n * a single static binary, no Python runtime required\n * no need to write a dedicated config file for most projects\n * compatible enough with testrepository’s workflow that I can switch projects over without retraining my fingers\n * a richer on-disk format that captures more about each run (git commit, command line, duration, exit code, concurrency)\n * good support for the languages I actually use day-to-day: Rust, Python, Go, and Node.js\n * mostly Do What I Mean (DWIM), e.g. getting me to know as quickly as possible what tests are failing and why, and being clever about doing this\n\n\n\nInquest reads and writes subunit v2 streams, so anything that can produce subunit (directly or via one of the many converters) can feed into it.\n\n## Quick start\n\nInquest can usually figure out how to run your tests on its own. In a Rust, Python, Go or Node.js project:\n\n\n $ cd my-project\n $ inq\n\n\nOr if the auto-detection doesn’t work, you can ask it to generate a config file and then run the tests:\n\n\n $ inq auto\n $ inq run\n\n\n`inq auto` writes an `inquest.toml` describing how to invoke the test runner; `inq run` runs the tests, captures the subunit stream, and stores the results in a `.inquest/` directory.\n\nFor a Rust project the generated config looks like:\n\n\n test_command = \"cargo subunit $IDOPTION\"\n test_id_option = \"--test $IDFILE\"\n test_list_option = \"--list\"\n\n\nAfter the first run, the usual queries work:\n\n\n $ inq stats # repository-wide statistics\n $ inq last # results of the most recent run\n $ inq failing # only the failing tests\n $ inq slowest # the slowest tests in the last run\n $ inq run --failing # re-run only what failed last time\n\n\nThe last one is the workflow I use most often: run the full suite once, fix the obvious failures, then iterate on `inq run --failing` until the list is empty.\n\n## A few things that aren’t in testrepository\n\nSome of the features that have grown in inquest beyond the original testrepository functionality:\n\n * **Timeouts.** `--test-timeout`, `--max-duration`, and `--no-output-timeout` will kill a test process that is hanging or has stopped producing output. `--test-timeout auto` derives a per-test timeout from the historical duration of that test, which is handy for catching tests that hang.\n\nOnce the test runner is killed, the test is marked as failed and the next test is started, so a broken test doesn’t hold up the whole suite.\n\n * **Ordering** `--order` can be used to run tests in a specific order, e.g. to run the slowest tests first, to run the tests that failed most recently first, or to run the widest variety of tests first to maximize the chance of finding a failure early on.\n\n * **Live progress.** `inq running` tails the in-progress subunit stream on disk and reports observed/expected test counts, percent complete, elapsed wall-clock time, and an ETA derived from each test’s historical duration. Useful when a CI run is taking longer than you’d like.\n\n * **Flakiness ranking.** `inq flaky` ranks tests by pass↔fail transitions in consecutive runs in which the test was recorded, so chronically broken tests rank low and genuinely flapping tests rank high.\n\n * **Bisecting test isolation issues.** `inq analyze-isolation <TEST>` binary-searches the test list to find the minimal set of other tests that cause a target test to fail when run together but pass in isolation. This one has paid for itself several times over already.\n\n * **Rerun a previous run verbatim.** `inq rerun <ID>` re-runs exactly the tests of a previous run, in the same order, forwarding the same `--` arguments that the original run used. `inq rerun -1` repeats the latest.\n\n * **Web based view.** `inq web` serves a web-based view of the repository, with a dashboard of recent runs and detailed views of individual runs and tests.\n\n\n\n\n## Migrating from testrepository\n\nIf you already have a `.testrepository/` directory full of historical runs, `inq upgrade` will migrate it into the new `.inquest/` format, with a progress bar for the impatient.\n\nThe legacy `.testr.conf` (INI) format is still understood, so existing projects don’t have to be converted to `inquest.toml` immediately — though the TOML format is preferred for new projects.\n\n## Trying it\n\nThe source is on GitHub at jelmer/inquest. To install from source:\n\n\n $ cargo install inquest\n\n\nIn a project with a Rust, Python, Go or Node.js test suite:\n\n\n $ inq\n\n\nBug reports and patches are welcome.",
"title": "Jelmer Vernooij: Inquest, a test result repository in Rust",
"updatedAt": "2026-05-03T10:00:00.000Z"
}