# Generating Tests at Comptime

**URL:** <https://ziggit.dev/t/generating-tests-at-comptime/6473>\
**Category:** Help\
**Tags:** testing\
**Created:** [October 22, 2024, 10:18am UTC](https://ziggit.dev/t/generating-tests-at-comptime/6473 "2024-10-22T10:18:16Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![koe](https://ziggit.dev/user_avatar/ziggit.dev/koe/32/9493_2.png) [@koe](https://ziggit.dev/u/koe)\
**Post date:** [October 22, 2024, 10:18am UTC](https://ziggit.dev/t/generating-tests-at-comptime/6473/1 "2024-10-22T10:18:16Z")

</div>

Hi all, apologies in advance if this is in any way a duplicate, I’ve tried to look around but couldn’t quite find a direct solution.

I am looking to automatically generate a bunch of tests at comptime based on a test suite consisting of many, many files.

Essentially, I would like to do something like:

```zig
comptime for (fixtures) |fixture| {
    test fixture.name {
        fixture.performTest();
    }
}

```

Where I generate `fixtures` at compile time by means of essentially `@embed`-ing a bunch of test files.

Naturally, I can just create a single, massive test. But this prevents me from seeing which tests fail without hacking my own reporting.

Has anyone hit a similar issue before and have a creative solution?

---

<div class="post-metadata">

**Author:** ![kavika13](https://ziggit.dev/letter_avatar_proxy/v4/letter/k/a9a28c/32.png) [@kavika13](https://ziggit.dev/u/kavika13)\
**Post date:** [October 22, 2024, 10:51am UTC](https://ziggit.dev/t/generating-tests-at-comptime/6473/2 "2024-10-22T10:51:16Z")

</div>

I haven’t tried it myself, but you might be able to spit out a generated source file and have a subsequent build step depend on it.  
My idea would be textual code generation, though, which might be a tad flaky. Though at least you’d be able to see the files the codegen output.

I don’t know if Zig has any other code generation method available yet or not, besides textual. It can generate types. Haven’t tried it with tests. I don’t know if they’re as “first class” as compile-time `type` is, yet.

As someone who has a background in writing test automation full time, I see the value of very big test suites. But also consider that one of the cool things about Zig is being able to put tests RIGHT next to the code it tests, and use them as a sort of documentation. Even if you’re going to build a big test suite (please do), make sure you put a few doc tests along side the functions you’re writing as well.

---

<div class="post-metadata">

**Author:** ![koe](https://ziggit.dev/user_avatar/ziggit.dev/koe/32/9493_2.png) [@koe](https://ziggit.dev/u/koe)\
**Post date:** [October 22, 2024, 11:13am UTC](https://ziggit.dev/t/generating-tests-at-comptime/6473/3 "2024-10-22T11:13:32Z")

</div>

Thanks for your reply.

Code gen is definitely a solution, although I agree that it is a tad flaky as you mention.

Based on your reply, I will probably have a read through the standard library code base to see if you can do something similar to what you can do with `@Type` 🙂 , that’s a great idea.

Responding on your point on test as documentation, to further contextualize my question, what I am writing is a comptime TOML parser that parses TOML to a Zig type (with again, `@Type`). To verify the library, I plan to use an existing test suite (consisting of TOML and JSON file pairs). Rather than porting each test to Zig (cumbersome + error prone, there are 500+ or so tests), I plan to automatically generate them with Zigs amazing comptime capabilities 🙂.

---

<div class="post-metadata">

**Author:** ![koe](https://ziggit.dev/user_avatar/ziggit.dev/koe/32/9493_2.png) [@koe](https://ziggit.dev/u/koe)\
**Post date:** [October 22, 2024, 12:44pm UTC](https://ziggit.dev/t/generating-tests-at-comptime/6473/4 "2024-10-22T12:44:07Z")

</div>

As an update I found a way to do it by digging through the standard library:

```zig
comptime {
    const files = .{"hay", "hey", "hooi", "needle"};
    for(files) |file| {
        _ = struct {
            test {
                try std.testing.expect(std.mem.eql(u8, file, "needle"));
            }
        };
    }
}

```

This serves my purpose well 🙂 ! That being said if someone knows how I can give these tests names that would be even better.

---

<div class="post-metadata">

**Author:** ![Sze](https://ziggit.dev/user_avatar/ziggit.dev/sze/32/496_2.png) [@Sze](https://ziggit.dev/u/Sze)\
**Post date:** [December 14, 2025, 12:41pm UTC](https://ziggit.dev/t/generating-tests-at-comptime/6473/5 "2025-12-14T12:41:02Z")

</div>

If you want the names to show up in the error message the only way I can think of is to make the name a comptime/generic parameter of a parent namespace and have the test namespaced underneath that, that way the name will show up in error messages.

```zig
const std = @import("std");

pub fn Test(comptime name: []const u8, Def: type) type {
    return struct {
        const reference = name;
        const def = Def;

        const Self = @This();
        test Self {
            try Def.impl();
        }
    };
}

comptime {
    const files = .{ "hay", "hey", "hooi", "needle" };
    for (files) |file| {
        _ = Test(file, struct {
            fn impl() !void {
                try std.testing.expect(std.mem.eql(u8, file, "needle"));
            }
        });
    }
}

```

Output:

```zig
1/4 testnames.Test("hay"[0..3],testnames.comptime__struct_163).decltest.Self...FAIL (TestUnexpectedResult)
/home/sze/development/workspace/zig/active/zig-x86_64-linux-0.15.2/lib/std/testing.zig:607:14: 0x11a1639 in expect (std.zig)
    if (!ok) return error.TestUnexpectedResult;
             ^
/home/sze/development/workspace/zig/learn/examples/testnames.zig:21:17: 0x11a16bf in impl (testnames.zig)
                try std.testing.expect(std.mem.eql(u8, file, "needle"));
                ^
/home/sze/development/workspace/zig/learn/examples/testnames.zig:11:13: 0x11a1736 in decltest.Self (testnames.zig)
            try Def.impl();
            ^
2/4 testnames.Test("hey"[0..3],testnames.comptime__struct_168).decltest.Self...FAIL (TestUnexpectedResult)
/home/sze/development/workspace/zig/active/zig-x86_64-linux-0.15.2/lib/std/testing.zig:607:14: 0x11a1639 in expect (std.zig)
    if (!ok) return error.TestUnexpectedResult;
             ^
/home/sze/development/workspace/zig/learn/examples/testnames.zig:21:17: 0x11a17bf in impl (testnames.zig)
                try std.testing.expect(std.mem.eql(u8, file, "needle"));
                ^
/home/sze/development/workspace/zig/learn/examples/testnames.zig:11:13: 0x11a1836 in decltest.Self (testnames.zig)
            try Def.impl();
            ^
3/4 testnames.Test("hooi"[0..4],testnames.comptime__struct_174).decltest.Self...FAIL (TestUnexpectedResult)
/home/sze/development/workspace/zig/active/zig-x86_64-linux-0.15.2/lib/std/testing.zig:607:14: 0x11a1639 in expect (std.zig)
    if (!ok) return error.TestUnexpectedResult;
             ^
/home/sze/development/workspace/zig/learn/examples/testnames.zig:21:17: 0x11a18bf in impl (testnames.zig)
                try std.testing.expect(std.mem.eql(u8, file, "needle"));
                ^
/home/sze/development/workspace/zig/learn/examples/testnames.zig:11:13: 0x11a1936 in decltest.Self (testnames.zig)
            try Def.impl();
            ^
1 passed; 0 skipped; 3 failed.
error: the following test command failed with exit code 1:
/home/sze/.cache/zig/o/09d1e4dd150f78b6175abfec5c775efa/test --seed=0xf1eaa028

```
