Como hacer testing en Bash

Scripts en Bash

Este es uno de los capítulos del tutorial Scripts en Bash. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.

Quizás el título de este capítulo del tutorial sea algo pretencioso. Pero desde luego, si aplicas el testing en Bash, si no eres ya un máster en Bash, vas camino de conseguirlo a marchas forzadas, eso sin lugar a dudas. Si has revisado, estudiado y practicado todos los otros capítulos del tutorial, este ya te viene de corrido. Es la pieza que te faltaba para completar el puzzle.

El testing no te garantiza que tus scripts en Bash vayan a estar exentos de errores, aunque mejoran sensiblemente la calidad de tu código, y te garantizan unos mejores resultados. Desde luego que si realizas todos los casos de uso, estarás muy cerca del éxito total.

Pero ¿que es esto del testing?¿como puedes aplicar el testing en Bash?

Como hacer testing en Bash

Como hacer testing en Bash

Por simplificar al máximo y aclarar un poco de que va esto del testing, indicarte que se trata de un proceso que te permite verificar y validar una funcionalidad o un caso o casos de uso.

Pongamos que implementas una función en Bash para convertir una frase a mayúsculas. El testing te permitiría verificar que esa funcionalidad que has implementado funciona de forma correcta. Así, le aplicas una serie de casos de uso, y compruebas que el resultado es el correcto. Este mismo caso, lo veremos en un ejemplo, para que veas lo práctico y funcional que es esto.

shUnit2

De los diferentes framework que hay disponibles para hacer test unitarios con Bash, me he quedado con shUnit2. Es el que mas sencillo me ha resultado para la configuración y puesta en marcha. Además los scripts de testeo siguen siendo scripts en Bash, con lo que se pueden revisar al igual que harías con cualquier otro script.

shUnit2 es un framework para realizar test unitarios de scripts basados en Bourne. Está diseñado para tener un comportamiento y funcionalidad similar a la que ofrece JUnit, PyUnit, etc.

Los shell que se han probado son,

  • sh
  • bash
  • dash
  • ksh
  • zsh

Instalación y configuración

El primera paso es preparar nuestro campo de pruebas, por llamarlo de alguna manera. Aunque el directorio principal puede ser cualquiera, en este caso, le he llamado testing para que quede claro. En tu caso, realmente solo necesitas que dentro de tu proyecto tengas un directorio llamado test que es donde se situará todo lo que necesitas para realizar el testing. El ejemplo que he realizado lo puedes encontrar en un repositorio en GitHub llamado testing en bash.

Una vez creado este directorio, y los directorios necesarios, donde tengas el código y lo que tu vayas a necesitar, el siguiente paso, es añadir un submodule de Git que te permitirá realizar los test.

Los pasos a realizar serían los siguientes,

mkdir testing
cd testing
mkdir src test
git init
git submodule add https://github.com/kward/shunit2.git test/shunit2

Dentro del directorio src tienes que añadir tus scripts, mientras que en el directorio test, colocarás tus test unitarios que quieras probar.

Configurando nuestro sistema de pruebas

Dentro del directorio test encontrarás el archivo test1.sh con algunos test que veremos mas adelante. En este archivo he añadido al final del mismo, las siguientes líneas de código. Es importante que este código esté al final,

# --- 👇 Aquí los scripts con el código a probar 👇 ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
oneTimeSetUp(){
    source "${SCRIPT_DIR}/../src/sample.sh"
}
# --- 👇 la librería que nos permite realizar las pruebas 👇 ---
# Load shUnit2
source "${SCRIPT_DIR}/shunit2/shunit2"

La variable $SCRIPT_DIR la he definido para tener el directorio en el que se encuentra el script de prueba. Está definido como ruta absoluta, lo que te ayudará para poder trabajar tanto con tus scripts como cono los test.

Funciones de ayuda

Existen una serie de funciones de ayuda que te facilitarán la realización de testing de forma mucho mas cómoda.

Asserts

Estas son las funciones que te permitirán realizar las comparaciones entre lo que debe obtenerse y lo que se obtiene. Estas son las siguientes,

  • assertEquals
  • assertNotEquals
  • assertSame
  • assertNotSame
  • assertContains
  • assertNotContains
  • assertNull
  • assertNotNull
  • assertTrue
  • assertFalse

Lo mismo tienes para los errores,

  • fail
  • failNotEquals
  • failSame
  • failNotSame
  • failFound
  • failNotFound

Saltando pruebas

En ocasiones y por las circunstancias que sean, sucede que necesitas saltar alguna de las pruebas. Por ejemplo, cuando la parte del código correspondiente no la tienes ya preparada, o porque no la necesitas en ese momento. En este caso, tienes tres funciones que te ayudarán,

  • startSkipping da inicio a la parte del código que quedará excluido del test
  • endSkipping exactamente igual que el anterior pero marca el fin.
  • isSkipping permite conocer si la línea está afectada de skipping.

Librerías y otras dependencias

Es posible que necesites realizar una serie de operaciones antes de realizar un test o después de realizarlo. Por ejemplo, imagina que en tu test creas un archivo temporal. Lo suyo, es que una vez terminado el test, borres ese archivo temporal. Pues estas funciones que te voy a indicar a continuación son útiles para realizar precisamente ese trabajo. Así, tienes las siguientes,

  • oneTimeSetUp esta función se ejecuta antes de que se ejecuten los test. Solo se ejecutará una vez. En esta función deberías introducir aquellas variables de entorno que quieras que estén disponibles para tus propios test.
  • oneTimeTearDown. Esta sería la función complementaria a la anterior, en el sentido de que se ejecuta al terminar todos los tests, y solo se ejecutará una vez. Al igual que en el caso anterior te resultará de interés para el caso de que quieras dejar tu campo de pruebas limpio como antes de comenzar las mismas.
  • setUp esta función se ejecutará antes de cada test.
  • tearDown lo mismo que la anterior para al final de cada test.

Algunos ejemplos

Aunque puedes encontrar muchos mas ejemplos en el repositorio de GitHub, te indico algunos para que veas lo sencillo que puede ser crear tus test unitarios y mejorar sensiblemente la calidad de tu código.

testApi200(){
    result=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "https://httpbin.org/status/200" -H  "accept: text/plain")
    assertEquals 200 "${result}"
}

testSaludo(){
    result=$(curl -s -X GET "https://httpbin.org/base64/SG9sYQo%3D" -H  "accept: text/html")
    assertEquals "Hola" "${result}"
}

Puedes encontrar muchos mas ejemplos en el repositorio que mi repositorio de GitHub.

El vídeo

En este vídeo te explico el funcionamiento de shUnit2 y como puedes integrarlo con tus scripts para hacer baterías de test.


Imagen de portada de Joshua Lawrence

Deja una respuesta

Tu dirección de correo electrónico no será publicada.