Pruebas unitarias en Bash: asegurando la calidad de tus scripts

La programación en Bash a menudo es considerada más un arte que una ciencia, un conjunto de comandos concatenados para resolver tareas específicas en sistemas UNIX. Sin embargo, con la creciente complejidad de los entornos de sistema y las aplicaciones, la necesidad de contar con código Bash robusto y confiable nunca ha sido tan imperativa. Las pruebas unitarias son una práctica de desarrollo de software que consiste en verificar que los componentes individuales de un programa funcionan como es esperado. En el ecosistema de Bash, esto puede representar un desafío por la ausencia de un marco de pruebas unitarias establecido como en otros lenguajes de alto nivel. Este artículo está dedicado a explorar las prácticas y herramientas que nos permitirán asegurar la calidad de nuestros scripts Bash a través de pruebas unitarias efectivas.

Comprendiendo las pruebas unitarias en Bash

La premisa fundamental de las pruebas unitarias es garantizar que cada función o componente del sistema hace exactamente lo que se supone que debe hacer. En el contexto de Bash, esto significa probar scripts o funciones individuales aisladas de otras partes del sistema o de recursos externos como archivos, servicios web, entre otros. La implementación de pruebas unitarias en Bash puede ser menos intuitiva que en otros lenguajes, dado que Bash no fue diseñado con pruebas en mente. Sin embargo, con las herramientas y técnicas adecuadas, es posible y se vuelve una tarea indispensable para cualquier desarrollador serio que busque mantener altos estándares de calidad.

Un enfoque fundamental para las pruebas unitarias en Bash es la utilización del ‘test command’ incorporado (conocido comúnmente como [ o [[), que permite realizar evaluaciones condicionales. Otro enfoque es emplear herramientas de terceros, como Bats (Bash Automated Testing System), shUnit2 o shellcheck, para proporcionar una estructura de pruebas más formal y con mayor soporte para reportes de errores y resultados de pruebas.

Estructurando scripts para la prueba

Antes de saltar a escribir pruebas, es crucial estructurar nuestros scripts de manera que sean testables. Esto a menudo significa adherirse a las buenas prácticas de programación, tales como la separación de las preocupaciones y la división del código en funciones puras pequeñas y reutilizables. Una función se considera ‘pura’ cuando su salida se determina únicamente por sus entradas, sin causar o depender de efectos secundarios externos.

Además, existen técnicas específicas en Bash para mejorar la testabilidad de los scripts. Una es el uso de ‘source’ para incluir scripts o funciones externas, facilitando la inyección de dependencias y el mockeo, o simulación, de comportamientos para las pruebas. Otra técnica es el manejo cuidadoso de la entrada y salida estándar, lo cual puede ayudar en la creación de pruebas predecibles que no dependan del contexto en el que se ejecuten.

Herramientas de pruebas para Bash

Existen distintas herramientas que pueden facilitar la escritura y ejecución de pruebas unitarias en Bash. Una de las más conocidas es Bats, que ofrece una sintaxis similar a la de los frameworks de pruebas de otros lenguajes, permitiendo escribir casos de pruebas con descripciones legibles e informes claros de su ejecución. ShUnit2 es otra opción popular, menos extensa que Bats, pero que puede ser más fácil de integrar en entornos existentes. Shellcheck, por su parte, es una herramienta de análisis estático que, sin ser un marco de pruebas propiamente dicho, ayuda a detectar muchos problemas comunes en los scripts de Bash que podrían llevar a errores en ejecución.

La elección de la herramienta dependerá de las necesidades específicas del proyecto y del entorno de desarrollo. Por ejemplo, si se está ejecutando un entorno de integración continua, es probable que se prefiera una herramienta que pueda producir resultados en un formato compatible con otros sistemas de reportes.

Escribiendo nuestra primera prueba unitaria en Bash

Para ilustrar cómo escribir una prueba unitaria en Bash, vamos a crear una función simple y su correspondiente prueba. Imaginemos que tenemos una función llamada ‘sumar’, que toma dos números como argumentos y devuelve su suma. La función podría verse algo así:

function sumar {
    local suma=$(( $1 + $2 ))
    echo $suma
}

Para probar esta función, podríamos escribir un script de prueba utilizando Bats que verifique el comportamiento esperado:

Con Bats, utilizaríamos una estructura como la siguiente para nuestro script de pruebas, donde ‘setup’ y ‘teardown’ son funciones opcionales que se ejecutan antes y después de cada prueba, respectivamente. El cuerpo de la prueba propiamente dicha verifica que la ejecución de la función ‘sumar’ con los argumentos 2 y 3 tenga como resultado 5, y si es así, la prueba pasa. Si el resultado fuese diferente, la prueba fallaría.

#!/usr/bin/env bats

@test "sumando 2 y 3" {
    resultado=$(sumar 2 3)
    [ "$resultado" -eq 5 ]
}

Manejando las pruebas y su mantenimiento

Una vez que tenemos una base de pruebas establecida, el mantenimiento de estas se convierte en una tarea crítica. Las pruebas unitarias deben estar vivas, evolucionando junto con el código que prueban. Esto implica actualizarlas conforme cambia la lógica de los scripts y añadir nuevas pruebas para cubrir nuevos casos o funcionalidades.

El mantenimiento también incluye la revisión periódica de las pruebas para verificar que sigan siendo relevantes y no se haya introducido redundancia o, peor aún, que las pruebas no se hayan vuelto falsamente tranquilizadoras al no cubrir adecuadamente el código que se supone que están probando.

Integrando las pruebas en el ciclo de desarrollo

La integración de pruebas unitarias en el ciclo de desarrollo de un proyecto Bash es esencial para su eficacia. Esto puede lograrse a través de la incorporación de pruebas en los ganchos de pre-commit de git, por ejemplo, asegurando que ninguna nueva actualización rompa funcionalidades existentes antes de que el código sea compartido con el equipo.

Además, la integración con sistemas de integración continua (CI) garantiza que las pruebas se ejecuten en un entorno limpio y controlado, aumentando la confianza en el código que se está desplegando en producción.

Conclusión

Las pruebas unitarias en Bash no son solo para grandes proyectos o para desarrolladores expertos. Son una herramienta que cualquier persona que escriba scripts Bash, no importa qué tan pequeños o grandes sean, debería considerar para mejorar la confiabilidad, la mantenibilidad y la calidad general del código. Con las prácticas y herramientas discutidas aquí, puedes dar tus primeros pasos hacia un desarrollo más profesional y seguro en Bash.

Te puede interesar

Deja una respuesta

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