Introdução
Zig fornece um conjunto de funções de assertion em std.testing que cobrem a maioria dos cenários de teste. Esta receita documenta cada uma com exemplos práticos. Diferente de frameworks como Jest ou JUnit, Zig mantém as assertions simples e explícitas.
Para testes básicos, veja Testes Unitários Básicos. Para testes com memória, consulte Testes com Allocator.
Pré-requisitos
- Zig instalado (versão 0.13+). Veja o guia de instalação
- Conhecimento básico de testes em Zig
expectEqual
Compara dois valores de mesmo tipo para igualdade:
const std = @import("std");
const testing = std.testing;
test "expectEqual - inteiros" {
try testing.expectEqual(@as(i32, 42), soma(20, 22));
}
test "expectEqual - enum" {
const Estado = enum { ativo, inativo };
try testing.expectEqual(Estado.ativo, obterEstado());
}
test "expectEqual - struct" {
const Ponto = struct { x: i32, y: i32 };
try testing.expectEqual(
Ponto{ .x = 1, .y = 2 },
criarPonto(1, 2),
);
}
test "expectEqual - optional" {
try testing.expectEqual(@as(?i32, 42), buscar(1));
try testing.expectEqual(@as(?i32, null), buscar(0));
}
expectEqualStrings
Compara strings (slices de u8) com mensagem de erro clara:
test "expectEqualStrings" {
try testing.expectEqualStrings("Zig Brasil", formatar("Zig", "Brasil"));
try testing.expectEqualStrings("", ""); // Strings vazias
}
Se falhar, mostra a diferença exata entre as strings esperada e obtida.
expectEqualSlices
Compara slices elemento por elemento:
test "expectEqualSlices - u8" {
const esperado = [_]u8{ 1, 2, 3, 4, 5 };
const obtido = try gerarSequencia(5);
try testing.expectEqualSlices(u8, &esperado, obtido);
}
test "expectEqualSlices - i32" {
const esperado = [_]i32{ 10, 20, 30 };
const obtido = [_]i32{ 10, 20, 30 };
try testing.expectEqualSlices(i32, &esperado, &obtido);
}
expect (booleano)
Verifica que uma condição é verdadeira:
test "expect" {
try testing.expect(1 + 1 == 2);
try testing.expect("abc".len == 3);
try testing.expect(ehPrimo(7));
try testing.expect(!ehPrimo(4));
}
expectError
Verifica que uma expressão retorna um erro específico:
fn dividir(a: f64, b: f64) !f64 {
if (b == 0) return error.DivisaoPorZero;
return a / b;
}
test "expectError" {
try testing.expectError(error.DivisaoPorZero, dividir(10, 0));
}
test "sem erro" {
const resultado = try dividir(10, 2);
try testing.expectEqual(@as(f64, 5.0), resultado);
}
Veja Error Sets Customizados.
expectApproxEqAbs (floats)
Compara floats com tolerância absoluta:
test "expectApproxEqAbs" {
const pi = calcularPi();
try testing.expectApproxEqAbs(@as(f64, 3.14159), pi, 0.001);
}
test "float com tolerância" {
const resultado = @sin(@as(f64, std.math.pi / 2.0));
try testing.expectApproxEqAbs(@as(f64, 1.0), resultado, 1e-10);
}
expectApproxEqRel (floats relativos)
Compara floats com tolerância relativa:
test "expectApproxEqRel" {
const grande = 1_000_000.0;
const quase_igual = 1_000_000.1;
try testing.expectApproxEqRel(grande, quase_igual, 1e-6);
}
expectFmt
Verifica a representação formatada de um valor:
test "expectFmt" {
try testing.expectFmt("42", "{}", .{@as(i32, 42)});
try testing.expectFmt("hello", "{s}", .{"hello"});
}
Matchers Customizados
Zig não tem um sistema de matchers extensível como Jest, mas você pode criar funções auxiliares:
fn expectMaiorQue(comptime T: type, valor: T, limite: T) !void {
if (valor <= limite) {
std.debug.print("Esperava > {}, obteve {}\n", .{ limite, valor });
return error.TestExpectedGreater;
}
}
fn expectContem(haystack: []const u8, needle: []const u8) !void {
if (std.mem.indexOf(u8, haystack, needle) == null) {
std.debug.print("'{s}' não contém '{s}'\n", .{ haystack, needle });
return error.TestExpectedContains;
}
}
fn expectEntre(comptime T: type, valor: T, min: T, max: T) !void {
if (valor < min or valor > max) {
std.debug.print("Esperava {} entre {} e {}\n", .{ valor, min, max });
return error.TestExpectedInRange;
}
}
test "matchers customizados" {
try expectMaiorQue(i32, 10, 5);
try expectContem("Zig Brasil", "Brasil");
try expectEntre(f64, 3.14, 3.0, 4.0);
}
Verificar Que NÃO Retorna Erro
test "operação bem-sucedida" {
// try já verifica - se houver erro, o teste falha
const resultado = try operacao();
try testing.expect(resultado > 0);
}
Testar Múltiplos Cenários
test "tabela de testes" {
const casos = [_]struct {
entrada: i32,
esperado: i32,
}{
.{ .entrada = 0, .esperado = 0 },
.{ .entrada = 1, .esperado = 1 },
.{ .entrada = 5, .esperado = 120 },
.{ .entrada = 10, .esperado = 3628800 },
};
for (casos) |caso| {
const resultado = fatorial(caso.entrada);
try testing.expectEqual(caso.esperado, resultado);
}
}
Conclusão
As assertions de std.testing cobrem a grande maioria dos cenários de teste. Para casos especiais, crie funções auxiliares que encapsulem verificações complexas. Mantenha os testes simples e focados em um comportamento por teste.
Para mais sobre testes, veja Testes Unitários Básicos, Testes com Allocator e Mocking e Stubbing.