Zig Test

zig test is a tool that can be used to quickly build and run Zig code to make sure behavior meets expectations. @import("builtin").is_test is available for code to detect whether the current build is a test build.

detect_test.zig

  1. const std = @import("std");
  2. const builtin = @import("builtin");
  3. const assert = std.debug.assert;
  4. test "builtin.is_test" {
  5. assert(builtin.is_test);
  6. }
  1. $ zig test detect_test.zig
  2. Test 1/1 builtin.is_test...OK
  3. All tests passed.

Zig has lazy top level declaration analysis, which means that if a function is not called, or otherwise used, it is not analyzed. This means that there may be an undiscovered compile error in a function because it is never called.

unused_fn.zig

  1. fn unused() i32 {
  2. return "wrong return type";
  3. }
  4. test "unused function" { }
  1. $ zig test unused_fn.zig
  2. Test 1/1 unused function...OK
  3. All tests passed.

Note that, while in Debug and ReleaseSafe modes, unreachable emits a call to @panic, in ReleaseFast and ReleaseSmall modes, it is really undefined behavior. The implementation of std.debug.assert is as simple as:

  1. pub fn assert(ok: bool) void {
  2. if (!ok) unreachable;
  3. }

This means that when testing in ReleaseFast or ReleaseSmall mode, assert is not sufficient to check the result of a computation:

assert.zig

  1. const std = @import("std");
  2. const assert = std.debug.assert;
  3. test "assert in release fast mode" {
  4. assert(false);
  5. }
  1. $ zig test assert.zig --release-fast
  2. Test 1/1 assert in release fast mode...OK
  3. All tests passed.

Note that although the above example shows the test passing, this is invoking unchecked Undefined Behavior. This documentation is showing only one possible outcome of this test.

Better practice for checking the output when testing is to use std.testing.expect:

test.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. test "assert in release fast mode" {
  4. expect(false);
  5. }
  1. $ zig test test.zig --release-fast
  2. Test 1/1 assert in release fast mode...test failure
  3. Tests failed. Use the following command to reproduce the failure:
  4. /home/andy/dev/zig/docgen_tmp/test

See the rest of the std.testing namespace for more available functions.

zig test has a few command line parameters which affect the compilation. See zig --help for a full list. The most interesting one is --test-filter [text]. This makes the test build only include tests whose name contains the supplied filter text. Again, thanks to lazy analysis, this can allow you to narrow a build to only a few functions in isolation.