Todos los artículos
bashunit

bashunit

bashunit es un framework de testing ligero y fácil de usar para Bash, repleto de características útiles como testing paralelo y de snapshots, dobles de test, data providers y toneladas de assertions incorporadas. Respaldado por documentación clara y una comunidad activa, se ha convertido en un favorito para testing confiable en Bash. Lo que comenzó como una simple frustración de desarrollo ha crecido hasta convertirse en una herramienta open-source que hace que el testing en Bash sea mucho más fácil y divertido.

blog-cover

bashunit es un framework de testing ligero y fácil de usar para Bash. Características como testing paralelo y de snapshots, dobles de test, data providers y toneladas de assertions incorporadas.

Respaldado por documentación clara y una comunidad activa, se ha convertido en un favorito para testing confiable en Bash. Lo que comenzó como una simple frustración de desarrollo ha crecido hasta convertirse en una herramienta open-source que hace que el testing en Bash sea mucho más fácil y divertido.

  1. La historia detrás de bashunit
  2. ¿Por qué crear otra librería de testing?
  3. ¿Cómo está hoy en día?
  4. Características principales
  5. Lightning tech talk

La historia detrás de bashunit

El viaje para crear bashunit comenzó con una simple frustración: trabajaba con un equipo donde cada commit tenía que empezar con el nombre del ticket. Como me gusta trabajar en pequeños pasos con commits rápidos e iterativos, añadir la clave y número del ticket a cada commit se convirtió en un gran obstáculo, ralentizando mi flujo de desarrollo con fricción innecesaria.

Después de unos días así, decidí automatizarlo. Git tiene un hook útil, prepare-commit-msg, que te permite alterar los mensajes de commit antes de que se finalicen. Creé un (script) en Bash que automáticamente obtiene la clave y número del ticket del nombre de la rama y lo inserta en el mensaje del commit, haciendo mi proceso más fluido y eficiente.

Como alguien que valora la mejora continua, comencé a añadir más características a este script. Sin embargo, se hizo evidente que mantener y probar estos cambios manualmente llevaba demasiado tiempo y era propenso a errores. Para hacer el desarrollo más seguro y eficiente, creé una función assert(enlace), permitiendo tests automatizados que verificaban el comportamiento esperado basado en la salida del script.

bashunit-original-assert.jpg

La función assert me permitió definir múltiples assertions en un archivo separado, facilitando la validación de que cualquier refactorización del hook original mantuviera el comportamiento esperado. Si un cambio rompía inadvertidamente la funcionalidad existente, lo señalaría instantáneamente, haciéndome saber de inmediato que algo necesitaba arreglarse. Esta configuración proporcionaba feedback inmediato y ayudaba a asegurar que cualquier actualización al script no interrumpiera su lógica prevista. Por ejemplo:

conventional-commits-original-tests.jpg

En el ejemplo anterior, notarás que ejecuto el “SCRIPT” real como el segundo argumento en la función assert, comparando su salida con el valor esperado proporcionado como primer argumento. Aquí, tenemos dos casos de test, cada uno exportando TEST_BRANCH para simular cómo el mensaje del commit variaría según el nombre de la rama. Esta configuración emula el comportamiento real, permitiéndonos probar cómo diferentes nombres de rama afectan el formato del mensaje del commit. Más ejemplos aquí.

Decidí separar la función assert de los casos de test, como se muestra aquí, para mantener las cosas modulares y reutilizables. Luego, creé un runner para ejecutar cada caso de test independientemente, reduciendo la interferencia entre tests y mejorando la confiabilidad. Puedes ver esa configuración aquí. Esta estructura hizo el testing automatizado más fácil y la refactorización más segura.

conventional-commits-call_test_functions.jpg

Esta fue una gran mejora porque facilitó separar los casos de test de la lógica del runner de tests en sí. Esta estructura clara ha simplificado tanto la creación como la gestión de tests.

conventional-commits-refactor-test-cases.jpg

Ahora los tests estaban organizados y tuve una idea:

cover

## Idea de seguimiento
Separar la lógica de testing en otro repositorio,
para que pueda ser reutilizada en cualquier lugar.

Y así comenzó. En ese momento, no sabía mucho sobre Bash o las mejores formas de usar un proyecto Bash como dependencia. Pero sabía que podía empezar usando un submódulo de Git, aunque no soy muy fan de ellos.

El 4 de septiembre de 2023, lancé la versión 0.1, que presentaba un runner funcional y una única función de assertion: assertEquals. Más tarde, se lanzó la versión 0.2, permitiendo que ./bashunit fuera un ejecutable independiente, ejecutable desde cualquier carpeta. Así es como se veía entonces:

bashunit-02-demo.jpg

Compartí el proyecto con algunos amigos que rápidamente se unieron para ayudar con la documentación, el sitio web, assertions adicionales, testing de snapshots y decisiones clave. Para enfatizar su espíritu open-source y propiedad comunitaria, lo moví a una organización que creamos específicamente para compartir proyectos OSS – convirtiéndolo en un proyecto verdaderamente colaborativo en lugar de uno individual.

¿Por qué crear otra librería de testing?

Ahora sé que existen otras librerías de testing para Bash. Pero cuando empecé con bashunit, no las conocía, y francamente, todavía no soy un experto en Bash. Para cuando me enteré de estas alternativas, ya era demasiado tarde — bashunit había ganado suficiente impulso y entusiasmo para seguir adelante.

Mientras que esas otras librerías pueden servir casos de uso específicos, usar Bash moderno, o ser desarrolladas por desarrolladores de Bash más experimentados, bashunit aspira a diferenciarse ofreciendo una gran experiencia de desarrollador, moldeada por años de trabajo con varios frameworks de testing.

Me preguntaron sobre las diferencias el 7 de septiembre de 2023, y aquí está mi respuesta: Pregunta: Diferencia con pgrange/bash_unit.

¿Cómo está hoy en día?

Hoy, puedes instalar bashunit via curl, Homebrew, MacPorts, descargando el último release de GitHub, o incluso compilándolo tú mismo desde el código fuente. Completamente open-source.

El proyecto está escrito en Bash 3.2 (de 2007) ya que esa es la versión por defecto en macOS — incluso ahora, en 2024. Esta compatibilidad significa que bashunit funciona sin problemas en esa versión, y planeo mantener el soporte para ella.

Para asegurar la calidad, probamos cada característica con tests unitarios, funcionales y de aceptación, haciendo que bashunit sea su propio “primer usuario” de cada nueva característica. También tenemos varios workflows de CI usando GitHub actions que ejecutan tests en diferentes plataformas para verificar compatibilidad y confirmar que todo funciona como se promete.

bashunit-ci.jpg

En junio de 2024, bashunit fue integrado en PHPStan para sus tests end-to-end, permitiendo el uso de las assertions de bashunit independientemente de su runner. Esta flexibilidad resultó ser muy útil.

El verano pasado, fui invitado a hablar sobre bashunit en la International PHP Conference en Berlín, junto con Manu, otro contribuidor. Este proyecto ha abierto puertas y ha llevado a mucha gratitud de usuarios que aprecian el trabajo que hemos puesto en él.

Características principales

bashunit incluye funciones clásicas del ciclo de vida como set_up, tear_down, set_up_before_script y tear_down_after_script.

También soporta una amplia gama de parámetros de línea de comandos y valores de configuración. Algunos de mis favoritos incluyen:

  • --parallel
  • --filter
  • --stop-on-failure
  • --verbose

También proporcionamos data providers para ejecutar los mismos casos de test con diferentes inputs.

Para dobles de test, bashunit ofrece mocks y spies. Estos funcionan dentro del mismo proceso que el test, pero actualmente no funcionan entre procesos — un área para mejorar.

Incluye potente testing de snapshots, facilitando la verificación de salidas de comandos o scripts a lo largo del tiempo.

bashunit ofrece un amplio conjunto de assertions nativas para casos de test, incluyendo:

  • assert_same
  • assert_equals
  • assert_contains
  • assert_matches
  • assert_string_starts_with
  • assert_array_contains
  • assert_successful_code
  • assert_general_error
  • assert_file_exists
  • assert_file_contains
  • assert_match_snapshot

Incluso puedes crear tus propias assertions personalizadas para extender las capacidades de bashunit.

Con más de 25 contribuidores y más de 325 estrellas en GitHub en solo un año de desarrollo en tiempo libre, estoy genuinamente orgulloso de lo que este proyecto se ha convertido.

Lightning tech talk

Recientemente, presenté una lightning tech talk en un meetup de hackers, haciendo una demo de bashunit a una audiencia de más de 100 personas. ¡Fue una experiencia increíble compartir esta herramienta con una audiencia tan comprometida!


Logo original de bashunit diseñado por Antonio.

Ssearch Dtheme Llang Jolder Knewer Ttoc Ccopy ?help

Atajos de Teclado

Navegación

HInicio
BBlog
RLecturas
LCambiar idioma

Acciones

SBuscar
DCambiar tema
CCopiar URL
GGIr arriba

Artículos

JArtículo anterior
KArtículo siguiente
TMostrar/ocultar índice

General

?Mostrar ayuda
EscCerrar