Cuando desarrollamos software en Zig, la calidad y la fiabilidad son fundamentales. Una de las formas más sencillas y directas de garantizar que nuestro código funciona como se espera es a través de pruebas unitarias. En Zig, el módulo std.testing ofrece una variedad de utilidades que facilitan la escritura de estas pruebas. En particular, expectEqualStrings resulta útil cuando necesitamos verificar que dos secuencias de caracteres (strings) sean idénticas.
¿Qué es std.testing.expectEqualStrings?
Esta función se ubica dentro del paquete std.testing y su propósito es comparar dos cadenas de tipo []const u8 (cadenas de bytes sin signo). Si las cadenas son iguales, la función devuelve true; si no, devuelve false y genera una excepción de prueba que falla el test.
Firma de la función
pub fn expectEqualStrings(comptime T: type, a: []const T, b: []const T) anyerror!void
En la firma se ve que:
comptime T: typeindica que la función es genérica y acepta cualquier tipo de elemento (por ejemplou8para cadenas ASCII ou32para Unicode).aybson las dos secuencias que se comparan.- La función devuelve
voidsi la comparación es exitosa, y lanza un error de tipoerror.TestFailedsi no lo es.
Uso básico
El ejemplo más sencillo consiste en comparar dos literales de cadena. A continuación se muestra un bloque de prueba completo con comentarios detallados.
const std = @import("std");
test "compara cadenas simples" {
// 1. Declaramos dos literales de cadena.
const a = "Hola, mundo!";
const b = "Hola, mundo!";
// 2. Usamos expectEqualStrings para comparar ambos literales.
// Si las cadenas son iguales, el test pasa sin problema.
// Si no, el test falla y se mostrará un mensaje con la diferencia.
try std.testing.expectEqualStrings(u8, a, b);
}
Explicación línea por línea
const std = @import("std");– Importa el paquete estándar de Zig.test "compara cadenas simples" { ... }– Declara una prueba con un nombre descriptivo.const a = "Hola, mundo!";– Define la primera cadena.const b = "Hola, mundo!";– Define la segunda cadena (identica a la primera).try std.testing.expectEqualStrings(u8, a, b);– Llama a la función de prueba; eltrymaneja el posible error.
Parámetros y tipos de retorno
La función es genérica, por lo que el primer parámetro indica el tipo de elemento que se está comparando. Los valores comunes son:
u8– Para cadenas ASCII o UTF‑8 sin caracteres extendidos.u16– Para cadenas UTF‑16.u32– Para cadenas Unicode completas (punto de código).
Ejemplo con Unicode:
test "compara cadenas Unicode" {
const hello = "¡Hola, 世界!";
// Aquí indicamos que estamos trabajando con u32 (puntos de código).
try std.testing.expectEqualStrings(u32, hello, hello);
}
Casos de uso típicos
- Verificar que una función que devuelve una cadena produce el resultado esperado.
- Comprobar la salida de una rutina de procesamiento de textos.
- Validar la correcta codificación de caracteres especiales.
- Testear la manipulación de strings en funciones de entrada/salida.
Ejemplo completo con explicación detallada
const std = @import("std");
// 1. Función que transforma un nombre a mayúsculas y agrega un saludo.
fn greet(name: []const u8) []const u8 {
// Creamos un buffer mutable con suficiente capacidad.
var buffer = std.ArrayList(u8).init(std.heap.page_allocator);
defer buffer.deinit();
// 2. Convertimos cada carácter a mayúscula y lo añadimos al buffer.
for (name) |c| {
const upper = std.ascii.toUpper(c);
try buffer.append(upper);
}
// 3. Construimos la cadena final con el saludo.
const saludo = "HELLO ";
try buffer.insertSlice(0, saludo);
// 4. Devolvemos la cadena como slice sin la capacidad interna.
return buffer.toOwnedSlice();
}
test "greet devuelve la cadena correcta" {
// 5. Cadena de entrada y la cadena esperada.
const input = "mario";
const expected = "HELLO MARIO";
// 6. Llamamos a la función.
const result = greet(input);
// 7. Comparamos el resultado con la cadena esperada.
// Si hay una diferencia, el test falla mostrando la diferencia exacta.
try std.testing.expectEqualStrings(u8, result, expected);
}
Desglose de cada línea del ejemplo
const std = @import("std");– Importa el paquete estándar.fn greet(name: []const u8) []const u8 { ... }– Define la función a probar.var buffer = std.ArrayList(u8).init(std.heap.page_allocator);– Crea un ArrayList mutable para construir la respuesta.defer buffer.deinit();– Libera la memoria cuando la función termine.for (name) |c| { ... }– Itera sobre cada carácter del nombre.const upper = std.ascii.toUpper(c);– Convierte el carácter a mayúscula.try buffer.append(upper);– Añade el carácter mayúsculo al buffer.const saludo = "HELLO ";– Define el saludo fijo.try buffer.insertSlice(0, saludo);– Inserta el saludo al inicio del buffer.return buffer.toOwnedSlice();– Devuelve la cadena resultante.test "greet devuelve la cadena correcta" { ... }– Define la prueba unitária.const input = "mario";– Cadena de prueba.const expected = "HELLO MARIO";– Resultado esperado.const result = greet(input);– Llamada a la función.try std.testing.expectEqualStrings(u8, result, expected);– Verificación de igualdad.
Buenas prácticas al usar expectEqualStrings
- Siempre especifica el tipo correcto (u8
