Skip to content
baskingspotPublic

About

A plain-text test runner, Go-style benchmarks, and compile-time test fixtures for Zig 0.16.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

testingx

A plain-text test runner, Go-style benchmarks, and compile-time test fixtures for Zig 0.16 and 0.17.

Zig's built-in test runner draws a progress display and speaks a binary protocol to the build runner, which is why output piped to a file is unreadable and why writing to stdout in a test can deadlock. testingx replaces it with plain text on stderr. The benchmark half follows Go's testing.B and prints the Go benchmark format, so benchstat compares two runs with no glue. The fixture helpers keep binary test data as base64 or hex text and organize fixtures in txtar archives, all read at compile time. One dependency, no dependencies of its own, Zig 0.16 and 0.17.

What is in it

  • Your first benchmark: a suite is a file with pub fn benchmarkMain(b: *testingx.B) !void. addBench builds it as a ReleaseFast executable.
  • Test runner flags: --format, --filter, --timeout, --count, --rerun-fails, --shuffle, and --slowest. A wrong filter fails instead of passing silently; --allow-empty-filter relaxes that for multi-binary builds.
  • Writing benchmarks: b.loop(), defer b.keepAlive(sink), b.setBytes, b.reportMetric, and b.run for sub-benchmarks. Names use benchfmt parts, so benchstat groups a matrix.
  • Embedded fixtures: testingx.b64 and testingx.hex decode one embedded file, and testingx.fixtures reads a txtar archive by name at compile time.
  • Artifacts: --artifacts=DIR gives each test a directory of files worth keeping when it fails, and deletes it when the test passes.
  • For library authors: .lazy = true plus if (b.pkg_hash.len != 0) return; keeps the runner and benchmarks out of a consumer's build.
  • Limits: what the compiler does not allow, such as parallel tests and subtests.

Not implemented:

  • Fuzz mode uses the built-in runner, which speaks the server protocol that .mode = .simple skips. Select the runner with a -Dfuzz option and leave .test_runner null for that build.
  • Tests run one at a time. std.testing keeps its allocator and I/O in globals, so there is nothing to parallelize safely.
  • A skip cannot carry a reason. error.SkipZigTest is the whole vocabulary.

Install

zig fetch --save https://baskingspot.dev/testingx/v0.4.0.tar.gz

Point the test runner at the dependency:

const testingx = b.dependency("testingx", .{ .target = target });

const tests = b.addTest(.{
    .root_module = mod,
    .test_runner = .{ .path = testingx.path("src/runner.zig"), .mode = .simple },
});
const run_tests = b.addRunArtifact(tests);
run_tests.addPassthruArgs();

On Zig 0.16, Run.addPassthruArgs does not exist yet. Forward the flags with if (b.args) |args| run_tests.addArgs(args); instead.

Benchmarks take one more step. testingx.addBench builds the suite and returns the run step. The guide has the wiring, including the .imports list the suite needs.

testingx builds with Zig 0.16 and 0.17.

Documentation

  • The guide covers adoption, flags, benchmark authoring, fixtures, and the library-author setup, with examples that compile.
  • The API reference documents every symbol.

Work on it

just ci

nix develop provides the toolchain. just lists the recipes, and just ci runs the tests, the lint, and the docs build.

License

MIT. See LICENSE. The logo files in docs/static/ are baskingspot marks and are not covered by it. See docs/static/LICENSE.

How it's made

Built with LLM assistance. How, in detail.

baskingspot

About

A plain-text test runner, Go-style benchmarks, and compile-time test fixtures for Zig 0.16.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages