mcpField
Z
zig-testing

zig-testing

github.com/mohitmishra786テスト・品質269450 回インストール18 週間前に更新
リポジトリ

zig-testing について

Zigの組み込みテストツールと手法を扱うスキルです。テストの実行と絞り込み、リーク検出、comptimeテスト、Zig 0.14で導入された組み込みファザーを解説します。

主な機能

  1. 01zig testとzig build testでテストを実行
  2. 02build.zigでテストステップを設定
  3. 03テスト実行の絞り込み
  4. 04テストアロケーターによるリーク検出
  5. 05comptimeテストの作成
  6. 06Zig 0.14以降の組み込みファザー

活用シーン

  1. 01Zigのソースファイルやライブラリをテストする
  2. 02メモリ割り当てのリークを確認する
  3. 03コンパイル時関数と型を検証する
  4. 04Zigの入力パーサーをファズテストする

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill zig-testing

インストール後、Claude Code で/zig-testingを入力して読み込まれたか確認します。

詳細

Zig のテスト

目的

Zig のテストシステムについて、エージェントをガイドします。zig build test と zig test、comptime テストのパターン、テストフィルター、リーク検出用のテストアロケーター、そして 0.14 で導入された Zig 組み込みのファジングテストを扱います。

トリガー

  • 「Zig でテストを書く方法と実行する方法を教えてください」
  • 「実行する Zig テストを絞り込むにはどうすればよいですか?」
  • 「Zig のテストでメモリーリークを検出するにはどうすればよいですか?」
  • 「Zig で comptime テストを書くにはどうすればよいですか?」
  • 「Zig の組み込みファザーを使うにはどうすればよいですか?」
  • 「Zig のライブラリーをテストするにはどうすればよいですか?」

ワークフロー

1. テストの作成と実行
// src/math.zig
const std = @import("std");
const testing = std.testing;

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

pub fn divide(a: f64, b: f64) !f64 {
    if (b == 0.0) return error.DivisionByZero;
    return a / b;
}

// Tests live in the same file or a dedicated test file
test "add: basic addition" {
    try testing.expectEqual(@as(i32, 5), add(2, 3));
    try testing.expectEqual(@as(i32, -1), add(2, -3));
}

test "add: identity" {
    try testing.expectEqual(@as(i32, 42), add(42, 0));
}

test "divide: normal case" {
    const result = try divide(10.0, 2.0);
    try testing.expectApproxEqAbs(result, 5.0, 1e-9);
}

test "divide: by zero returns error" {
    try testing.expectError(error.DivisionByZero, divide(1.0, 0.0));
}
# Run all tests in a single file
zig test src/math.zig

# Run all tests via build system
zig build test

# Verbose output
zig build test -- --verbose

# Run specific test by name (substring match)
zig build test -- --test-filter "add"
2. build.zig のテスト設定
// build.zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // Unit test step
    const unit_tests = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const run_unit_tests = b.addRunArtifact(unit_tests);

    // Integration tests (separate executable)
    const integration_tests = b.addTest(.{
        .root_source_file = b.path("tests/integration.zig"),
        .target = target,
        .optimize = optimize,
    });
    const run_integration = b.addRunArtifact(integration_tests);

    // `zig build test` runs both
    const test_step = b.step("test", "Run all tests");
    test_step.dependOn(&run_unit_tests.step);
    test_step.dependOn(&run_integration.step);

    // `zig build test-unit` runs only unit tests
    const unit_step = b.step("test-unit", "Run unit tests");
    unit_step.dependOn(&run_unit_tests.step);
}
3. テストアロケーター — リーク検出

std.testing.allocator はテストモードで GeneralPurposeAllocator をラップし、各テストの終了時にリークを報告します。

const std = @import("std");
const testing = std.testing;

test "ArrayList: no leaks" {
    // testing.allocator detects leaks and reports them
    var list = std.ArrayList(u32).init(testing.allocator);
    defer list.deinit();   // MUST defer to return memory

    try list.append(1);
    try list.append(2);
    try list.append(3);

    try testing.expectEqual(@as(usize, 3), list.items.len);
    // If you forget defer list.deinit(), test reports a leak
}

test "custom allocation" {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer {
        const leaked = gpa.deinit();
        // .ok means no leaks; .leak means memory was not freed
        testing.expect(leaked == .ok) catch @panic("memory leaked!");
    }
    const allocator = gpa.allocator();

    const buf = try allocator.alloc(u8, 1024);
    defer allocator.free(buf);  // leak if forgotten
}
4. テストのアサーション
const testing = std.testing;

// Equality
try testing.expectEqual(expected, actual);
try testing.expectEqualStrings("hello", result_str);
try testing.expectEqualSlices(u8, expected_slice, actual_slice);

// Approximate equality (for floats)
try testing.expectApproxEqAbs(expected, actual, tolerance);
try testing.expectApproxEqRel(expected, actual, tolerance);

// Errors
try testing.expectError(error.MyError, might_fail());
try testing.expect(condition);    // basic boolean assertion

// Comparison
try testing.expect(a < b);
try testing.expectStringStartsWith(str, "prefix");
try testing.expectStringEndsWith(str, "suffix");
5. Comptime テスト

Zig では comptime でテストを実行できます。これはコンパイル時定数や型レベルのチェックに役立ちます。

const std = @import("std");
const testing = std.testing;

// Test comptime functions
fn isPowerOfTwo(n: comptime_int) bool {
    return n > 0 and (n & (n - 1)) == 0;
}

// Comptime assert (compile error if false)
comptime {
    std.debug.assert(isPowerOfTwo(16));
    std.debug.assert(!isPowerOfTwo(15));
    std.debug.assert(isPowerOfTwo(1024));
}

// Test with comptime-known values (runs at comptime in test mode)
test "isPowerOfTwo: comptime" {
    comptime {
        try testing.expect(isPowerOfTwo(8));
        try testing.expect(!isPowerOfTwo(7));
    }
}

// Type-level testing
test "type properties" {
    // Verify alignment and size at comptime
    comptime {
        try testing.expectEqual(8, @alignOf(u64));
        try testing.expectEqual(4, @sizeOf(u32));
        try testing.expectEqual(true, @typeInfo(u8).Int.signedness == .unsigned);
    }
}
6. ファジングテスト(Zig 0.14 以降)

Zig 0.14 では、カバレッジ誘導型ファジングを使用する組み込みファザーが導入されました。

// fuzz_target.zig
const std = @import("std");

// Fuzz entry point: receives arbitrary bytes
export fn fuzz(input: []const u8) void {
    // Call the function under test with fuzz input
    parseInput(input) catch {};
}

fn parseInput(data: []const u8) !void {
    if (data.len < 4) return error.TooShort;
    const magic = std.mem.readInt(u32, data[0..4], .little);
    if (magic != 0xDEADBEEF) return error.BadMagic;
    // ... more parsing
}
# Run the fuzzer
zig build fuzz -Dfuzz=fuzz_target

# With corpus directory
zig build fuzz -Dfuzz=fuzz_target -- corpus/

# The fuzzer generates and saves interesting inputs to corpus/
# Crashes are saved as artifacts

# Reproduce a specific crash
zig build test-fuzz -- corpus/crash-xxxx

build.zig でのファジング設定については、以下を参照してください。

// build.zig addition
const fuzz_exe = b.addExecutable(.{
    .name = "fuzz",
    .root_source_file = b.path("src/fuzz_target.zig"),
    .target = target,
    .optimize = .ReleaseSafe,
});
fuzz_exe.root_module.fuzz = true;   // enable fuzzing instrumentation
const fuzz_step = b.step("fuzz", "Run fuzzer");
fuzz_step.dependOn(&b.addRunArtifact(fuzz_exe).step);

関連スキル

  • build.zig の設定とテストステップのセットアップには、skills/zig/zig-build-system を使用します
  • comptime アサーションでテストする comptime 評価パターンには、skills/zig/zig-comptime を使用します
  • 代替ファジングフレームワークとしての libFuzzer/AFL には、skills/runtimes/fuzzing を使用します
  • Zig テストでの AddressSanitizer には、skills/runtimes/sanitizers を使用します

コメント