🎓 A1Learner
🔍
0 of 55 lessons completed

Zig Testing

Testing is running small checks that prove a piece of code gives the right answer. Zig has testing built in, so a test file runs with one command and reports every check.

One function, two passing tests

The add function sits above its tests in the same file. Each test asks expectEqual to compare a result with the known answer.

const std = @import("std");

fn add(a: i32, b: i32) i32 {
    return a + b;
}

test "add works" {
    try std.testing.expectEqual(@as(i32, 5), add(2, 3));
}

test "add zero" {
    try std.testing.expectEqual(@as(i32, 4), add(4, 0));
}

expect checks a true or false claim

The expect helper takes a condition instead of two values. The second test uses ! to check that seven is not even.

const std = @import("std");

fn isEven(n: i32) bool {
    return @rem(n, 2) == 0;
}

test "four is even" {
    try std.testing.expect(isEven(4));
}

test "seven is odd" {
    try std.testing.expect(!isEven(7));
}

Argument order does not change the answer

The max function should return nine whichever way round the arguments go. Two tests pin down both orders.

const std = @import("std");

fn max(a: i32, b: i32) i32 {
    if (a > b) {
        return a;
    }
    return b;
}

test "max picks larger" {
    try std.testing.expectEqual(@as(i32, 9), max(3, 9));
}

test "max works reversed" {
    try std.testing.expectEqual(@as(i32, 9), max(9, 3));
}

Example

const std = @import("std");

fn subtotal(unit_price: i32, count: i32) i32 {
    return unit_price * count;
}

fn shipping(total: i32) i32 {
    if (total >= 50) {
        return 0;
    }
    return 5;
}

test "subtotal multiplies" {
    try std.testing.expectEqual(@as(i32, 36), subtotal(12, 3));
}

test "shipping free at fifty" {
    try std.testing.expectEqual(@as(i32, 0), shipping(50));
}

test "shipping costs five" {
    try std.testing.expectEqual(@as(i32, 5), shipping(20));
}

Key points

  • Test block: a block written with the test keyword and a name in quotes.
  • expectEqual: a helper from std.testing that fails the test when two values differ.
  • expect: a helper from std.testing that fails the test when a condition is false.
  • Test file: a file of tests and the functions they check, with no main function.
  • Report: the test runner prints one line per test and a summary line at the end.

In this example, two small shop functions sit at the top of the file. The first test checks that subtotal multiplies a unit price by a count. The next two tests check both sides of the shipping rule, free at fifty and five below it. The report shows one OK line per test and ends with all three passed.

Note

Zig tests live in the same file as the code they check, with no extra testing tool to install.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What happens when expectEqual compares two values that differ?