Curso de Shell Scripting

Los tests automáticos ayudan a:

  • Detectar errores rápidamente.
  • Evitar que nuevas modificaciones rompan funcionalidades anteriores.
  • Aumentar la calidad y confianza en el código.

En este módulo aprenderás a usar bats-core, la herramienta estándar para testear scripts de shell.


15.1. Instalación de bats-core

En Linux (Debian/Ubuntu):

1sudo apt update
2sudo apt install bats

En macOS con Homebrew:

1brew install bats-core

Verifica la instalación:

1bats --version

15.2. Estructura típica de un proyecto con tests

mi_proyecto/
├── bin/
│   └── script.sh
└── tests/
    └── script_test.bats

✅ Mantén los tests en una carpeta separada (por ejemplo tests/).


15.3. Sintaxis básica de un test en bats

Un archivo de test termina en .bats y está formado por bloques @test.

Ejemplo tests/saludo_test.bats:

1#!/usr/bin/env bats
2
3@test "Muestra saludo" {
4  run ./bin/saludo.sh
5  [ "$status" -eq 0 ]
6  [[ "$output" == "Hola mundo" ]]
7}

▸ Explicación

  • run <comando> → ejecuta el comando y guarda:

    • $status → código de salida (0 = éxito).
    • $output → salida en la consola.
  • [ "$status" -eq 0 ] → comprueba que el script terminó correctamente.

  • [[ "$output" == "Hola mundo" ]] → comprueba que la salida es la esperada.


15.4. Crear un script para probar

bin/saludo.sh:

1#!/usr/bin/env bash
2set -Eeuo pipefail
3
4echo "Hola mundo"

Dale permisos de ejecución:

1chmod +x bin/saludo.sh

15.5. Ejecutar los tests

1bats tests/saludo_test.bats

Salida esperada:

✓ Muestra saludo

1 test, 0 failures

👉 El símbolo indica que el test pasó correctamente.


15.6. Comprobando argumentos

Script bin/suma.sh:

1#!/usr/bin/env bash
2set -Eeuo pipefail
3
4if [[ $# -ne 2 ]]; then
5  echo "Uso: $0 num1 num2"
6  exit 1
7fi
8
9echo $(( $1 + $2 ))

Test tests/suma_test.bats:

1#!/usr/bin/env bats
2
3@test "Suma correcta de dos números" {
4  run ./bin/suma.sh 5 7
5  [ "$status" -eq 0 ]
6  [[ "$output" == "12" ]]
7}
8
9@test "Falla si no hay argumentos" {
10  run ./bin/suma.sh
11  [ "$status" -ne 0 ]
12  [[ "$output" == "Uso: ./bin/suma.sh num1 num2" ]]
13}

Ejecución:

1bats tests/suma_test.bats

Salida:

✓ Suma correcta de dos números
 ✓ Falla si no hay argumentos

2 tests, 0 failures

15.7. Uso de archivos temporales en tests

Para scripts que leen o escriben archivos, usa setup y teardown para preparar y limpiar datos antes y después de cada test.

Ejemplo tests/log_test.bats:

1#!/usr/bin/env bats
2
3setup() {
4  TMPFILE=$(mktemp)
5}
6
7teardown() {
8  rm -f "$TMPFILE"
9}
10
11@test "Escribe en el archivo temporal" {
12  echo "Hola" > "$TMPFILE"
13  run cat "$TMPFILE"
14  [ "$status" -eq 0 ]
15  [[ "$output" == "Hola" ]]
16}

15.8. Integración con CI/CD

Puedes integrar los tests en pipelines (por ejemplo en GitHub Actions).

Ejemplo de workflow .github/workflows/test.yml:

1name: Test Scripts
2
3on: [push, pull_request]
4
5jobs:
6  test:
7    runs-on: ubuntu-latest
8    steps:
9      - uses: actions/checkout@v3
10      - name: Install bats
11        run: sudo apt update && sudo apt install -y bats
12      - name: Run tests
13        run: bats tests/

👉 Cada vez que subas cambios al repositorio, se ejecutarán los tests automáticamente.


🏋️‍♂️ Ejercicio práctico 1

Crea un proyecto calculadora:

calculadora/
├── bin/
│   └── resta.sh
└── tests/
    └── resta_test.bats
  1. El script resta.sh debe aceptar dos números y mostrar su resta.
  2. Si no recibe los dos números, debe mostrar un mensaje de error y salir con código distinto de 0.
  3. Escribe los tests para comprobar ambos casos.

🏋️‍♂️ Ejercicio práctico 2

Crea un script procesa_archivo.sh que:

  1. Acepte un archivo como argumento.
  2. Cuente cuántas líneas tiene (wc -l).
  3. Devuelva error si el archivo no existe.

Escribe un test que:

  • Cree un archivo temporal con texto de ejemplo.
  • Compruebe que el conteo es correcto.
  • Compruebe que falla cuando el archivo no existe.

✅ Buenas prácticas

  1. ✅ Escribe tests simples y enfocados en una funcionalidad concreta.
  2. ✅ Usa setup y teardown para preparar datos y limpiar al final.
  3. ✅ Comprueba código de salida ($status) además de la salida ($output).
  4. ✅ Mantén la carpeta tests/ organizada y con nombres descriptivos.
  5. ✅ Integra los tests en un pipeline de CI/CD para detectar errores temprano.
  • Loading...