---
title: "Unit Tests em Zig: Fundamentos do Sistema de Testes Built-in"
url: "https://ziglang.com.br/tutoriais/zig-unit-tests-fundamentos/"
markdown_url: "https://ziglang.com.br/tutoriais/zig-unit-tests-fundamentos.MD"
description: "Domine o sistema de testes built-in do Zig. Assertions, expectativas, testes parametrizados com comptime, testando erros e edge cases. Tutorial completo em portugues."
date: "2026-02-21"
author: ""
---

# Unit Tests em Zig: Fundamentos do Sistema de Testes Built-in

Domine o sistema de testes built-in do Zig. Assertions, expectativas, testes parametrizados com comptime, testando erros e edge cases. Tutorial completo em portugues.


Zig possui um dos sistemas de testes mais elegantes entre linguagens de programacao de sistemas. Testes sao cidadaos de primeira classe na linguagem — nao ha necessidade de frameworks, bibliotecas externas ou configuracoes complexas. Neste artigo, exploramos os fundamentos do sistema de testes built-in do Zig e como usa-lo efetivamente.

> Para o basico de testes em Zig, confira [Testes em Zig](/tutoriais/testes-zig/).

## O Sistema de Testes do Zig

Testes em Zig sao blocos `test` declarados junto ao codigo. Eles sao executados com `zig build test` ou `zig test arquivo.zig`.

### Primeiro Teste

```zig
const std = @import("std");
const expect = std.testing.expect;

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

test "soma basica" {
    try expect(soma(2, 3) == 5);
    try expect(soma(-1, 1) == 0);
    try expect(soma(0, 0) == 0);
}

test "soma com overflow" {
    // Zig detecta overflow em modo debug
    try expect(soma(std.math.maxInt(i32), 0) == std.math.maxInt(i32));
}
```

Execute com:

```bash
zig test arquivo.zig
# Saida: All 2 tests passed.
```

### Tipos de Assertions

```zig
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const expectError = std.testing.expectError;
const expectEqualStrings = std.testing.expectEqualStrings;
const expectEqualSlices = std.testing.expectEqualSlices;
const expectApproxEqAbs = std.testing.expectApproxEqAbs;

test "tipos de assertions" {
    // Igualdade basica
    try expectEqual(@as(i32, 42), soma(40, 2));

    // Strings
    const nome = "Zig Brasil";
    try expectEqualStrings("Zig Brasil", nome);

    // Slices
    const a = [_]u8{ 1, 2, 3 };
    const b = [_]u8{ 1, 2, 3 };
    try expectEqualSlices(u8, &a, &b);

    // Floats (com tolerancia)
    try expectApproxEqAbs(@as(f64, 3.14159), @as(f64, 3.14160), 0.001);
}
```

### Testando Erros

Um dos pontos fortes do Zig e o tratamento explicito de erros, e o sistema de testes reflete isso:

```zig
const std = @import("std");
const expect = std.testing.expect;
const expectError = std.testing.expectError;

const MathError = error{
    DivisaoPorZero,
    Overflow,
};

fn dividir(a: i32, b: i32) MathError!i32 {
    if (b == 0) return MathError.DivisaoPorZero;
    return @divTrunc(a, b);
}

test "divisao normal" {
    const resultado = try dividir(10, 2);
    try expect(resultado == 5);
}

test "divisao por zero retorna erro" {
    try expectError(MathError.DivisaoPorZero, dividir(10, 0));
}

test "divisao com catch" {
    const resultado = dividir(10, 0) catch |err| {
        try expect(err == MathError.DivisaoPorZero);
        return;
    };
    _ = resultado;
    // Se chegou aqui, o teste deveria ter falhado
    return error.TestExpectedError;
}
```

## Testes Parametrizados com Comptime

O comptime de Zig permite criar testes parametrizados sem macros:

```zig
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;

fn fatorial(n: u64) u64 {
    if (n <= 1) return 1;
    return n * fatorial(n - 1);
}

test "fatorial parametrizado" {
    const casos = .{
        .{ 0, 1 },
        .{ 1, 1 },
        .{ 2, 2 },
        .{ 3, 6 },
        .{ 4, 24 },
        .{ 5, 120 },
        .{ 10, 3628800 },
    };

    inline for (casos) |caso| {
        const entrada = caso[0];
        const esperado = caso[1];
        try expectEqual(@as(u64, esperado), fatorial(entrada));
    }
}
```

### Gerando Testes para Multiplos Tipos

```zig
const std = @import("std");
const expect = std.testing.expect;

fn maxGenerico(comptime T: type, a: T, b: T) T {
    return if (a > b) a else b;
}

fn testarMax(comptime T: type) !void {
    try expect(maxGenerico(T, 1, 2) == 2);
    try expect(maxGenerico(T, 5, 3) == 5);
    try expect(maxGenerico(T, 7, 7) == 7);
}

test "max para i32" {
    try testarMax(i32);
}

test "max para u64" {
    try testarMax(u64);
}

test "max para f32" {
    try testarMax(f32);
}
```

## Allocator de Teste

O `std.testing.allocator` detecta memory leaks automaticamente:

```zig
const std = @import("std");
const expect = std.testing.expect;

fn duplicarString(allocator: std.mem.Allocator, str: []const u8) ![]u8 {
    const copia = try allocator.alloc(u8, str.len);
    @memcpy(copia, str);
    return copia;
}

test "duplicar string sem leak" {
    const resultado = try duplicarString(std.testing.allocator, "teste");
    defer std.testing.allocator.free(resultado);

    try std.testing.expectEqualStrings("teste", resultado);
}

// Se voce esquecer o defer free, o teste FALHA com:
// "Test leaked memory" - detectado automaticamente!
```

## Organizando Testes em Projetos

### Testes no Mesmo Arquivo

```zig
// src/calculadora.zig
pub fn soma(a: i32, b: i32) i32 {
    return a + b;
}

pub fn multiplica(a: i32, b: i32) i32 {
    return a * b;
}

// Testes ficam no mesmo arquivo — removidos do binario de producao
test "operacoes basicas" {
    const expect = @import("std").testing.expect;
    try expect(soma(2, 3) == 5);
    try expect(multiplica(3, 4) == 12);
}
```

### Referenciando Testes de Submodulos

```zig
// src/main.zig ou src/root.zig
const calculadora = @import("calculadora.zig");
const parser = @import("parser.zig");
const utils = @import("utils.zig");

// Forcar execucao de testes em todos os modulos
comptime {
    _ = calculadora;
    _ = parser;
    _ = utils;
}

// Testes especificos de integracao
test "integracao calculadora-parser" {
    // ...
}
```

### Configurando no build.zig

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

    // Executavel principal
    const exe = b.addExecutable(.{
        .name = "meu-projeto",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Testes
    const testes = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const run_testes = b.addRunArtifact(testes);
    const test_step = b.step("test", "Executar testes");
    test_step.dependOn(&run_testes.step);

    b.installArtifact(exe);
}
```

## Exercicios

1. **Stack com testes:** Implemente uma stack generica com testes para push, pop, peek, isEmpty e deteccao de leak.

2. **Parser de CSV:** Crie um parser de CSV simples com testes parametrizados cobrindo edge cases (campos vazios, aspas, newlines).

3. **Testes de contrato:** Escreva testes que verifiquem invariantes de uma estrutura de dados (ex: BST sempre ordenada).

---

## Proximo Artigo

No proximo artigo, exploramos [padroes de teste avancados](/tutoriais/zig-testing-avancado/artigo-2-test-patterns/): mocks, stubs, dependency injection e table-driven tests.

### Conteudo Relacionado

- [Testes em Zig](/tutoriais/testes-zig/) — Introducao
- [Zig Build System](/tutoriais/zig-build-system/) — Configuracao de testes
- [Tratamento de Erros em Zig](/tutoriais/tratamento-de-erros-em-zig/) — Error unions

---

*Duvidas sobre testes em Zig? Participe da comunidade Zig Brasil!*
