Zig Test Blocks in Depth
A test block is a named check that Zig runs with zig test. One run can hold many test blocks, and Zig runs each one in turn.
Two blocks, one run
Each block checks one function. Zig runs both blocks and reports both results.
const std = @import("std");
fn add(a: i32, b: i32) i32 {
return a + b;
}
fn double(n: i32) i32 {
return n * 2;
}
test "add works" {
try std.testing.expectEqual(@as(i32, 5), add(2, 3));
}
test "double works" {
try std.testing.expectEqual(@as(i32, 8), double(4));
}Boolean checks
A boolean function needs blocks for both true and false cases. Each block holds one assertion here.
const std = @import("std");
fn isEven(n: i32) bool {
return @rem(n, 2) == 0;
}
test "even number is even" {
try std.testing.expect(isEven(4));
}
test "odd number is not even" {
try std.testing.expect(!isEven(5));
}
test "zero is even" {
try std.testing.expect(isEven(0));
}Several checks in one block
One block can hold several assertions about the same function. The block still counts as one test.
const std = @import("std");
fn add(a: i32, b: i32) i32 {
return a + b;
}
fn double(n: i32) i32 {
return n * 2;
}
fn square(n: i32) i32 {
return n * n;
}
test "add cases" {
try std.testing.expectEqual(@as(i32, 5), add(2, 3));
try std.testing.expectEqual(@as(i32, 0), add(-1, 1));
try std.testing.expectEqual(@as(i32, -4), add(-2, -2));
}
test "double cases" {
try std.testing.expectEqual(@as(i32, 6), double(3));
try std.testing.expectEqual(@as(i32, 0), double(0));
}
test "square cases" {
try std.testing.expectEqual(@as(i32, 9), square(3));
try std.testing.expectEqual(@as(i32, 16), square(-4));
}Example
const std = @import("std");
fn add(a: i32, b: i32) i32 {
return a + b;
}
fn double(n: i32) i32 {
return n * 2;
}
fn isEven(n: i32) bool {
return @rem(n, 2) == 0;
}
fn square(n: i32) i32 {
return n * n;
}
test "add works" {
try std.testing.expectEqual(@as(i32, 7), add(3, 4));
}
test "double works" {
try std.testing.expectEqual(@as(i32, 10), double(5));
}
test "even check works" {
try std.testing.expect(isEven(6));
}
test "square works" {
try std.testing.expectEqual(@as(i32, 25), square(5));
}Key points
- Test block: a test block is a named check that Zig runs when you run zig test.
- A test name is a short string that says what the block checks.
- Assertion: an assertion is a check that a value is what you expect.
- Use try before an assertion, so a failed check fails the test that holds it.
- Zig runs every test block in turn and reports each result separately.
- Keep each block to one idea, so a failure points at one small piece of behavior.
This run holds four blocks, one for each small function. Each block checks a single value, so a failure would point at one function. Together the four blocks cover the four functions in one run.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A run holds three test blocks. How many blocks does zig test run?