What Snag gives you
Declarative suites
A suite is a TOML file: variables, tags, timeouts, and one entry per test. No test-harness boilerplate, no build step — the manifest is the contract between your repo and the runner.
Real assertions, not JSON matchers
Assertions are Rhai scripts, so a test can branch, loop, chain requests, and walk a decoded body by dotted path — while still failing with one readable message.
Reports for whoever is watching
The same run renders as a colored terminal report, JSON, JSONL, TeamCity service messages (IntelliJ draws a native test tree), or JUnit XML for the rest of CI.
Parallel by default, serial when it matters
Tests run across a worker pool sized to your CPUs. Mark a test parallel_safe = false and it runs alone, before the pool starts.
Timeouts that actually fire
A timeout caps both the HTTP client and the script interpreter, so a hung socket and a runaway loop both end the test instead of the run.
Built for CI ergonomics
Filter by name, id, or tag; retry flaky tests and see the attempt count; shuffle with a seed for reproducible ordering; exit codes distinguish “tests failed” from “could not run”.
A suite is two files
The manifest says what to run; the script says what must be true. Nothing else is required.
title = "Checkout API"
timeout = "10s"
[variables]
base_url = "https://api.example.com"
[[test]]
id = "cart-create"
name = "POST /carts creates a cart"
tags = ["smoke"]
file = "./cart_create.snag"
let res = post(`${base_url}/carts`)
.header("authorization", basic("demo", env("API_PASSWORD")))
.json(#{ currency: "EUR" })
.send();
assert_status(res, 201);
assert_faster_than(res, 800);
assert_eq(field(res.json(), "currency"), "EUR");