---
title: "Testes Baseados em Propriedades com Zig"
url: "https://ziglang.com.br/artigos/testes-baseados-em-propriedades-com-zig/"
markdown_url: "https://ziglang.com.br/artigos/testes-baseados-em-propriedades-com-zig.MD"
description: "Testes baseados em propriedades em Zig. Geradores de dados, verificação de invariantes, shrinking e integração com fuzzing. Tutorial completo."
date: "2026-02-21"
author: "Zig Brasil"
---

# Testes Baseados em Propriedades com Zig

Testes baseados em propriedades em Zig. Geradores de dados, verificação de invariantes, shrinking e integração com fuzzing. Tutorial completo.


# Testes Baseados em Propriedades com Zig

Testes tradicionais verificam exemplos específicos. Testes baseados em propriedades verificam que uma propriedade vale para QUALQUER entrada. Em vez de testar que `sort([3,1,2]) == [1,2,3]`, testamos que "para qualquer array, o resultado de sort é ordenado".

## Propriedades vs Exemplos

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

fn meuSort(slice: []u32) void {
    std.mem.sort(u32, slice, {}, std.sort.asc(u32));
}

// Teste por exemplos (tradicional)
test "sort: exemplo específico" {
    var dados = [_]u32{ 3, 1, 4, 1, 5, 9, 2, 6 };
    meuSort(&dados);
    try std.testing.expectEqualSlices(u32, &.{ 1, 1, 2, 3, 4, 5, 6, 9 }, &dados);
}

// Teste por propriedades (abrangente)
test "propriedade: sort produz resultado ordenado" {
    var rng = std.Random.DefaultPrng.init(42);

    for (0..1000) |_| {
        // Gerar array aleatório
        var dados: [100]u32 = undefined;
        for (&dados) |*v| v.* = rng.random().int(u32);

        const original_len = dados.len;
        meuSort(&dados);

        // Propriedade 1: resultado é ordenado
        for (1..dados.len) |i| {
            try std.testing.expect(dados[i - 1] <= dados[i]);
        }

        // Propriedade 2: tamanho não muda
        try std.testing.expectEqual(original_len, dados.len);
    }
}

test "propriedade: sort é idempotente" {
    var rng = std.Random.DefaultPrng.init(123);

    for (0..1000) |_| {
        var dados: [50]u32 = undefined;
        for (&dados) |*v| v.* = rng.random().int(u32);

        meuSort(&dados);
        const primeira = dados;

        meuSort(&dados);

        // sort(sort(x)) == sort(x)
        try std.testing.expectEqualSlices(u32, &primeira, &dados);
    }
}
```

## Framework de Property Testing

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

fn PropertyTest(comptime T: type) type {
    return struct {
        rng: std.Random.DefaultPrng,
        iteracoes: u32,

        const Self = @This();

        pub fn init(seed: u64, iteracoes: u32) Self {
            return .{
                .rng = std.Random.DefaultPrng.init(seed),
                .iteracoes = iteracoes,
            };
        }

        pub fn verificar(
            self: *Self,
            propriedade: *const fn (T) bool,
            gerador: *const fn (*std.Random.DefaultPrng) T,
        ) !void {
            for (0..self.iteracoes) |i| {
                const valor = gerador(&self.rng);
                if (!propriedade(valor)) {
                    std.debug.print("Propriedade violada na iteração {d}\n", .{i});
                    return error.PropriedadeViolada;
                }
            }
        }
    };
}
```

## Propriedades Comuns

### Roundtrip (Ida e Volta)

```zig
test "propriedade: serialize/deserialize roundtrip" {
    var rng = std.Random.DefaultPrng.init(42);

    for (0..1000) |_| {
        const original = Ponto{
            .x = @bitCast(rng.random().int(u32)),
            .y = @bitCast(rng.random().int(u32)),
        };

        var buf: [8]u8 = undefined;
        original.serializar(&buf);

        const restaurado = Ponto.deserializar(&buf);

        // deserialize(serialize(x)) == x
        try std.testing.expectEqual(original.x, restaurado.x);
        try std.testing.expectEqual(original.y, restaurado.y);
    }
}
```

### Invariantes de Estrutura de Dados

```zig
test "propriedade: HashMap mantém todas as chaves inseridas" {
    var rng = std.Random.DefaultPrng.init(42);
    var map = std.AutoHashMap(u32, u32).init(std.testing.allocator);
    defer map.deinit();

    var chaves_inseridas = std.ArrayList(u32).init(std.testing.allocator);
    defer chaves_inseridas.deinit();

    // Inserir N chaves aleatórias
    for (0..500) |_| {
        const chave = rng.random().int(u32);
        const valor = rng.random().int(u32);
        try map.put(chave, valor);
        try chaves_inseridas.append(chave);
    }

    // Propriedade: toda chave inserida deve ser encontrável
    for (chaves_inseridas.items) |chave| {
        try std.testing.expect(map.contains(chave));
    }
}
```

## Conclusão

Testes baseados em propriedades complementam testes por exemplos ao verificar invariantes sobre espaços enormes de entradas possíveis. Em Zig, a combinação de `std.Random` para geração de dados, loops de verificação e o fuzzer built-in permite criar suítes de property testing poderosas sem dependências externas.

Testes baseados em propriedades existem em diversas linguagens. Conheça o proptest em <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust</a> e a biblioteca Hypothesis em <a href="https://python.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'python.dev.br' })">Python</a>, que popularizou essa abordagem de testes.

## Conteúdo Relacionado

- [Fuzz Testing em Zig](/tutoriais/zig-testing-avancado/artigo-3-fuzz-testing/) — Fuzzing
- [Property Testing em Zig](/tutoriais/zig-property-testing/) — Tutorial detalhado
- [Unit Tests em Zig](/tutoriais/zig-testing-avancado/artigo-1-unit-tests-fundamentos/) — Fundamentos
- [Test Patterns](/tutoriais/zig-testing-avancado/artigo-2-test-patterns/) — Padrões de teste
- [CI/CD com Zig](/tutoriais/zig-testing-avancado/artigo-5-ci-cd-testing/) — Automação
