---
title: "Perguntas de Entrevista sobre Testing em Zig"
url: "https://ziglang.com.br/entrevistas/perguntas-de-entrevista-sobre-testing-em-zig/"
markdown_url: "https://ziglang.com.br/entrevistas/perguntas-de-entrevista-sobre-testing-em-zig.MD"
description: "Perguntas de entrevista sobre testes em Zig: std.testing, expect, test allocator, TDD, mocking, testes de integração e boas práticas."
date: "2026-02-21"
author: "Zig Brasil"
---

# Perguntas de Entrevista sobre Testing em Zig

Perguntas de entrevista sobre testes em Zig: std.testing, expect, test allocator, TDD, mocking, testes de integração e boas práticas.


# Perguntas de Entrevista sobre Testing em Zig

Testes são fundamentais em qualquer base de código profissional. O Zig tem suporte a testes integrado diretamente na linguagem com blocos `test`, um allocator de teste que detecta memory leaks e integração com o build system. Este guia cobre perguntas práticas sobre testing em Zig para entrevistas.

## Perguntas e Respostas

### 1. Como funciona o sistema de testes do Zig?

No Zig, testes são blocos `test "nome"` que vivem junto ao código-fonte. O compilador pode executá-los via `zig test arquivo.zig`. Os blocos `test` não são compilados em builds normais — apenas quando `zig test` é executado.

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

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

test "somar dois positivos" {
    try std.testing.expectEqual(@as(i32, 5), somar(2, 3));
}

test "somar com zero" {
    try std.testing.expectEqual(@as(i32, 7), somar(7, 0));
}

test "somar negativos" {
    try std.testing.expectEqual(@as(i32, -3), somar(-1, -2));
}
```

Cada bloco `test` é executado isoladamente. Se um `try` falha, o teste é reportado como falho com informação detalhada sobre o valor esperado vs. recebido.

### 2. Qual a diferença entre `expect`, `expectEqual` e `expectEqualStrings`?

```zig
const testing = std.testing;

test "expect — verifica booleano" {
    const x: i32 = 10;
    try testing.expect(x > 5);       // Verifica condição booleana
    try testing.expect(x != 0);
}

test "expectEqual — verifica igualdade de valores" {
    try testing.expectEqual(@as(i32, 42), 42);           // Inteiros
    try testing.expectEqual(@as(f64, 3.14), 3.14);       // Floats exatos
    try testing.expectEqual(@as(?i32, null), @as(?i32, null)); // Optionals
}

test "expectEqualStrings — compara conteúdo de strings" {
    const nome = "Zig";
    try testing.expectEqualStrings("Zig", nome);
    // Diferente de expectEqual, mostra diff detalhado em caso de falha
}

test "expectEqualSlices — compara slices elemento a elemento" {
    const esperado = [_]u8{ 1, 2, 3 };
    const obtido = [_]u8{ 1, 2, 3 };
    try testing.expectEqualSlices(u8, &esperado, &obtido);
}

test "expectApproxEqAbs — floats com tolerância" {
    try testing.expectApproxEqAbs(@as(f64, 3.14159), 3.14, 0.01);
}

test "expectError — verifica que erro específico é retornado" {
    const resultado: anyerror!i32 = error.Overflow;
    try testing.expectError(error.Overflow, resultado);
}
```

### 3. O que é o testing allocator e por que é importante?

O `std.testing.allocator` é um allocator especial que rastreia todas as alocações e, ao final do teste, verifica se toda memória foi liberada. Se houver leak, o teste falha automaticamente.

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

fn criarLista(allocator: std.mem.Allocator) !std.ArrayList(i32) {
    var lista = std.ArrayList(i32).init(allocator);
    try lista.append(1);
    try lista.append(2);
    try lista.append(3);
    return lista;
}

test "lista sem memory leak" {
    var lista = try criarLista(testing.allocator);
    defer lista.deinit(); // Sem isso, o teste FALHA!

    try testing.expectEqual(@as(usize, 3), lista.items.len);
}

test "demonstração de leak detection" {
    // Se comentar o defer, o teste falha com:
    // "memory leak detected" + endereço e stack trace da alocação
    var buf = try testing.allocator.alloc(u8, 100);
    defer testing.allocator.free(buf);
    buf[0] = 42;
    try testing.expectEqual(@as(u8, 42), buf[0]);
}
```

### 4. Como organizar testes em projetos maiores?

```zig
// src/math.zig
pub fn fatorial(n: u64) u64 {
    if (n <= 1) return 1;
    var r: u64 = 1;
    for (2..n + 1) |i| r *= i;
    return r;
}

// Testes inline — vivem junto ao código
test "fatorial" {
    const testing = @import("std").testing;
    try testing.expectEqual(@as(u64, 1), fatorial(0));
    try testing.expectEqual(@as(u64, 120), fatorial(5));
}

// src/main.zig — referencia testes de submódulos
const math = @import("math.zig");

test {
    // Força o compilador a incluir testes de todos os imports
    @import("std").testing.refAllDecls(@This());
    _ = math; // Inclui testes de math.zig
}
```

No `build.zig`, configure testes com:

```zig
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);
const test_step = b.step("test", "Executa testes unitários");
test_step.dependOn(&run_unit_tests.step);
```

### 5. Como testar código que depende de I/O ou estado externo?

No Zig, a abordagem idiomática é injetar dependências via parâmetros (dependency injection):

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

/// Processador que aceita qualquer Writer (injeção de dependência).
pub fn processar(dados: []const u8, writer: anytype) !usize {
    var contagem: usize = 0;
    for (dados) |c| {
        if (c >= 'A' and c <= 'Z') {
            try writer.writeByte(c + 32); // lowercase
            contagem += 1;
        } else {
            try writer.writeByte(c);
        }
    }
    return contagem;
}

test "processar converte maiúsculas" {
    var buf: [256]u8 = undefined;
    var stream = std.io.fixedBufferStream(&buf);
    const writer = stream.writer();

    const convertidos = try processar("Hello WORLD", writer);

    try std.testing.expectEqual(@as(usize, 7), convertidos);
    try std.testing.expectEqualStrings("hello world", stream.getWritten());
}
```

### 6. Como simular (mock) dependências em testes?

O Zig não tem um framework de mocking nativo, mas comptime generics permitem injeção limpa:

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

/// Interface genérica via comptime — aceita implementação real ou mock.
fn HttpHandler(comptime Fetcher: type) type {
    return struct {
        pub fn obterStatus(fetcher: *Fetcher, url: []const u8) !u16 {
            const response = try fetcher.fetch(url);
            return response.status;
        }
    };
}

// Mock para testes
const MockFetcher = struct {
    chamadas: usize = 0,

    const Response = struct { status: u16 };

    pub fn fetch(self: *MockFetcher, url: []const u8) !Response {
        self.chamadas += 1;
        _ = url;
        return .{ .status = 200 };
    }
};

test "HttpHandler com mock" {
    var mock = MockFetcher{};
    const Handler = HttpHandler(MockFetcher);

    const status = try Handler.obterStatus(&mock, "https://example.com");

    try testing.expectEqual(@as(u16, 200), status);
    try testing.expectEqual(@as(usize, 1), mock.chamadas);
}
```

### 7. Como testar código concorrente em Zig?

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

fn Contador() type {
    return struct {
        const Self = @This();
        valor: std.atomic.Value(u32),

        pub fn init() Self {
            return .{ .valor = std.atomic.Value(u32).init(0) };
        }

        pub fn incrementar(self: *Self) void {
            _ = self.valor.fetchAdd(1, .monotonic);
        }

        pub fn obter(self: *const Self) u32 {
            return self.valor.load(.monotonic);
        }
    };
}

test "contador atômico com múltiplas threads" {
    var contador = Contador().init();

    const num_threads = 4;
    const incrementos_por_thread = 1000;

    var threads: [num_threads]std.Thread = undefined;
    for (&threads) |*t| {
        t.* = try std.Thread.spawn(.{}, struct {
            fn func(c: *Contador()) void {
                for (0..incrementos_por_thread) |_| {
                    c.incrementar();
                }
            }
        }.func, .{&contador});
    }

    for (threads) |t| t.join();

    try testing.expectEqual(
        @as(u32, num_threads * incrementos_por_thread),
        contador.obter(),
    );
}
```

### 8. Como usar zig test com filtros e opções?

```bash
# Executar todos os testes
zig test src/main.zig

# Filtrar por nome do teste
zig test src/main.zig --test-filter "fatorial"

# Com sumário detalhado
zig test src/main.zig --summary all

# Sem captura de stderr (mostra std.debug.print)
zig test src/main.zig 2>&1
```

### 9. Como testar funções que podem causar panic?

No Zig, `@panic` não é catchable em código normal, mas em testes existe uma técnica usando `std.testing.expectEqual` com comportamento de runtime:

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

fn dividir(a: i32, b: i32) i32 {
    if (b == 0) @panic("divisão por zero");
    return @divTrunc(a, b);
}

test "dividir funciona normalmente" {
    try std.testing.expectEqual(@as(i32, 5), dividir(10, 2));
    try std.testing.expectEqual(@as(i32, -3), dividir(-9, 3));
}

// Para testar panic, a abordagem idiomática é usar error unions
// em vez de @panic, para que erros sejam testáveis:
fn dividirSeguro(a: i32, b: i32) !i32 {
    if (b == 0) return error.DivisaoPorZero;
    return @divTrunc(a, b);
}

test "dividirSeguro retorna erro para zero" {
    try std.testing.expectError(error.DivisaoPorZero, dividirSeguro(10, 0));
}
```

### 10. Como escrever testes de propriedade (property-based testing)?

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

fn inverterSlice(comptime T: type, slice: []T) void {
    if (slice.len <= 1) return;
    var i: usize = 0;
    var j = slice.len - 1;
    while (i < j) : ({
        i += 1;
        j -= 1;
    }) {
        const tmp = slice[i];
        slice[i] = slice[j];
        slice[j] = tmp;
    }
}

test "propriedade: inverter duas vezes volta ao original" {
    var prng = std.Random.DefaultPrng.init(42);
    const random = prng.random();

    // Testa com múltiplas entradas aleatórias
    for (0..100) |_| {
        const tamanho = random.intRangeAtMost(usize, 0, 50);
        var dados = try testing.allocator.alloc(u8, tamanho);
        defer testing.allocator.free(dados);

        // Preenche com dados aleatórios
        random.bytes(dados);

        // Salva cópia do original
        var original = try testing.allocator.alloc(u8, tamanho);
        defer testing.allocator.free(original);
        @memcpy(original, dados);

        // Inverte duas vezes
        inverterSlice(u8, dados);
        inverterSlice(u8, dados);

        // Propriedade: deve voltar ao original
        try testing.expectEqualSlices(u8, original, dados);
    }
}

test "propriedade: ordenar é idempotente" {
    var prng = std.Random.DefaultPrng.init(123);
    const random = prng.random();

    for (0..50) |_| {
        const tamanho = random.intRangeAtMost(usize, 1, 30);
        var dados = try testing.allocator.alloc(i32, tamanho);
        defer testing.allocator.free(dados);

        for (dados) |*d| d.* = random.int(i32);

        // Ordena
        std.mem.sort(i32, dados, {}, std.sort.asc(i32));

        // Propriedade: já está ordenado
        try testing.expect(std.sort.isSorted(i32, dados, {}, std.sort.asc(i32)));
    }
}
```

### 11. Como medir cobertura de testes em Zig?

O Zig possui suporte experimental a cobertura de código via LLVM:

```bash
# Compila com instrumentação de cobertura
zig test -fllvm --coverage src/main.zig

# Gera relatório (usando llvm-cov)
llvm-profdata merge default.profraw -o default.profdata
llvm-cov show ./zig-out/test -instr-profile=default.profdata
```

### 12. Quais as boas práticas de testing em Zig?

1. **Use `testing.allocator`** para detectar leaks automaticamente
2. **Teste junto ao código** — blocos `test` no mesmo arquivo
3. **Prefira error unions a @panic** para código testável
4. **Injete dependências** via parâmetros genéricos (comptime)
5. **Nomeie testes descritivamente** — `test "fatorial de zero retorna 1"`
6. **Use `refAllDecls`** no main para incluir testes de submódulos
7. **Teste edge cases** — null, vazio, overflow, zero

## Recursos Relacionados

- [std.testing](/stdlib/std-testing/) — Referência completa do módulo
- [std.debug](/stdlib/std-debug/) — Assertions e depuração
- [std.log](/stdlib/std-log/) — Logging para diagnóstico
- [Perguntas de Entrevista: Error Handling](/entrevistas/perguntas-error-handling-zig/)
- [Perguntas de Entrevista: Memória](/entrevistas/perguntas-memoria-zig/)
