I’ve been a very big fan of data driven testing / table driven testing, however I don’t feel like this pattern is very well supported by Zig, so I wanted to know how other people approach this problem.
As far as I know the Zig standard library does not employ these testing techniques for example in ldexp.zig (Codeberg is down so copying the code here).
test ldexp {
// subnormals
try expect(ldexp(@as(f16, 0x1.1FFp14), -14 - 9 - 15) == math.floatTrueMin(f16));
try expect(ldexp(@as(f32, 0x1.3FFFFFp-1), -126 - 22) == math.floatTrueMin(f32));
try expect(ldexp(@as(f64, 0x1.7FFFFFFFFFFFFp-1), -1022 - 51) == math.floatTrueMin(f64));
try expect(ldexp(@as(f80, 0x1.7FFFFFFFFFFFFFFEp-1), -16382 - 62) == math.floatTrueMin(f80));
try expect(ldexp(@as(f128, 0x1.7FFFFFFFFFFFFFFFFFFFFFFFFFFFp-1), -16382 - 111) == math.floatTrueMin(f128));
try expect(ldexp(math.floatMax(f32), -128 - 149) > 0.0);
try expect(ldexp(math.floatMax(f32), -128 - 149 - 1) == 0.0);
}
The big advantage of data driven testing for me is that the test does not “fail fast” instead each failure will be shown individually.
Go handles this in a nice manner by using subtests aoc/go/cmd/02/02_test.go at master · nunokaeru/aoc · GitHub
In C and C++ you can use macros to create different test cases, for example in CATCH a test could look like:
TEST_CASE("int")
{
auto [a, b] = GENERATE(table<int, int>({
{0,0},
{1,1},
{2,2},
}));
REQUIRE(a == b);
}
I’ve found a way to (ab)use comptime to create these types of tests in Zig but I am not super happy with the approach. Here’s an example:
test "not duplicated" {
comptime {
const values = [_]u64{
12,
13,
12312,
41141,
1992191921992,
};
for (values) |n| {
_ = NotDuplicatedTest(n);
}
}
}
fn NotDuplicatedTest(
comptime number: u64,
) type {
return struct {
test {
var intBuffer: [20]u8 = undefined;
try std.testing.expect(!duplicates(intBuffer[0..], number));
}
};
}
Has anyone tried to approach this topic and has a better solution for this?