The most common way is to have a test block in the ‘main’ file of the module that references all other files in the module. See the Zig standard library for an example:
Combined with all the pub const blah = @import("blah.zig"); lines in std.zig, it will run all the tests in those files as well when running zig test lib/std/std.zig or addTest with .root_source_file = .{ .path = "lib/std/std.zig" }.
Modules as in the new build system terminology context. How do you link the dependencies in that regard then? zig test lib/std/std.zig cannot resolve the modules (if there is, like “utils” or “ast” in the OP, or you don’t use modules at all like the stdlib). How to do that with addTest?
const std = @import("std");
const utils = @import("utils");
test "something" {
const result = utils.foo();
try std.testing.expect(result);
}
As you noted, this will make it harder to run using zig test (but not impossible, zig build will end up running zig test with command line arguments to provide the module definitions, you can use --verbose when doing zig build ... to see which commands actually get run)
In latest Zig, both b.addTest and b.AddExecutable will return a *Step.Compile, so they share same methods, you can just test.addModule like what you do for exe.