¿Cómo usar std.testing.expectEqualStrings?

¿Cómo usar std.testing.expectEqualStrings?

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: type indica que la función es genérica y acepta cualquier tipo de elemento (por ejemplo u8 para cadenas ASCII o u32 para Unicode).
  • a y b son las dos secuencias que se comparan.
  • La función devuelve void si la comparación es exitosa, y lanza un error de tipo error.TestFailed si 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; el try maneja 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

Comments

No comments yet. Why don’t you start the discussion?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *