Guiones de Bash de pruebas unitarias

Tenemos un sistema que tiene algunos scripts bash que se ejecutan además del código de Java. Como intentamos probar todo lo que podría romperse, y esos scripts bash pueden romperse, queremos probarlos.

El problema es que es difícil probar los scripts bash.

¿Hay alguna manera o una mejor práctica para probar scripts bash? ¿O deberíamos dejar de usar los scripts bash y buscar soluciones alternativas que puedan probarse?

En realidad, existe un marco de prueba de unidades para scripts de shell . No lo he usado yo mismo, pero podría valer la pena echarle un vistazo.

Preguntas similares se han hecho antes:

  • Pruebas unitarias para scripts de shell
  • Probar todo en los scripts de Shell

Recibí la siguiente respuesta de un grupo de discusión:

es posible importar (incluir, lo que sea) un procedimiento (función, cualquiera que sea su nombre) desde un archivo externo. Esa es la clave para escribir un guión de prueba: divide el guión en procedimientos independientes que luego pueden importarse tanto en el guión en ejecución como en el guión de prueba, y luego tiene el guión de ejecución lo más simple posible.

Este método es como dependency injection para scripts y suena razonable. Es preferible evitar las secuencias de comandos bash y usar un lenguaje más comprobable y menos oscuro.

Prueba de Bash compatible con TAP : Bash Automated Testing System

bats-core

¿Por qué dices que es “difícil” probar scripts bash?

¿Qué pasa con los contenedores de prueba como:

#!/bin/bash set -e errors=0 results=$($script_under_test $args<&1 let errors+=1 } echo "$results" | grep -q $expected1 || { echo "Test Failed. Expected $expected1" let errors+=1 } # and so on, et cetera, ad infinitum, ad nauseum [ "$errors" -gt 0 ] && { echo "There were $errors errors found" exit 1 } 

Epoxy es un marco de prueba de Bash que diseñé principalmente para probar otro software, pero también lo uso para probar módulos de bash, incluidos él mismo y Carton .

Las ventajas principales son una sobrecarga de encoding relativamente baja, anidamiento de aserciones ilimitadas y selección flexible de aserciones para verificar.

Hice una presentación comparándola con BeakerLib , un marco utilizado por algunos en Red Hat.

Prueba bashtest . Es una forma simple de probar tus scripts. Por ejemplo, tiene do-some-work.sh que cambia algunos archivos de configuración. Por ejemplo, agregue la nueva línea PASSWORD = 'XXXXX' al archivo de configuración /etc/my.cfg .

Usted escribe los comandos bash línea por línea y luego verifica la salida.

Instalar:

 pip3 install bashtest 

Crear pruebas es solo escribir comandos bash.

Archivo test-do-some-work.bashtest :

 # run the script $ ./do-some-work.sh > /dev/null # testing that the line "PASSWORD = 'XXXXX'" is in the file /etc/my.cfg $ grep -Fxq "PASSWORD = 'XXXXX'" /etc/my.cfg && echo "YES" YES 

Ejecutar pruebas:

 bashtest *.bashtest 

Puedes encontrar algunos ejemplos aquí y aquí

Tal vez esto se puede usar o contribuir a

https://thorsteinssonh.github.io/bash_test_tools/

Destinado a escribir resultados en el protocolo TAP, que imagino que es bueno para CI, y bueno para aquellos que quieren entornos de shell. Imagino que algunas cosas se ejecutan en entornos de shell, por lo que algunos podrían argumentar que deberían probarse en su entorno de shell.

Prueba a assert.sh

 source "./assert.sh" local expected actual expected="Hello" actual="World!" assert_eq "$expected" "$actual" "not equivalent!" # => x Hello == World :: not equivalent! 

¡Espero eso ayude!

Nikita Sobolev escribió una excelente publicación de blog comparando algunos marcos de prueba de bash diferentes: pruebas de aplicaciones Bash

Para los impacientes: la conclusión de Nikita fue utilizar Bats, pero parece que Nikita se perdió el proyecto Bats-core , que me parece que será el que utilizará en el futuro ya que el proyecto original de los Bats no se ha mantenido activamente desde 2013.

Me gusta bastante shell2junit , una utilidad para generar salida de tipo JUnit a partir de las pruebas de script Bash. Esto es útil porque el informe generado puede leerse luego mediante sistemas de integración continua, como los complementos JUnit para Jenkins y Bamboo.

Si bien shell2junit no proporciona el marco completo de scripts de Bash como shunit2 , sí permite un buen informe de los resultados de las pruebas.

Es posible que desee echar un vistazo a bash_unit:

https://github.com/pgrange/bash_unit

Me resulta difícil justificar el uso de bash para scripts más grandes cuando Python tiene enormes ventajas:

  • Try / Except permite escribir scripts más robustos con la capacidad de deshacer cambios en caso de error.
  • No tiene que usar una syntax oscura como ‘ if [ x"$foo" = x"$bar"]; then ... if [ x"$foo" = x"$bar"]; then ... ‘que es propenso a errores.
  • Fácil análisis de opciones y argumentos usando el módulo getopt (y hay un módulo aún más fácil para analizar argumentos, pero el nombre se me escapa).
  • Python le permite trabajar con listas / dictados y objetos en lugar de cadenas básicas y matrices.
  • Acceda a las herramientas de lenguaje adecuadas, tales como regex, bases de datos (seguro que puede canalizar todo en el comando mysql en bash, pero no es la forma más agradable de escribir código).
  • No necesita preocuparse por usar la forma correcta de $* o "$*" o "$@" o $1 o "$1" , los espacios en los nombres de archivo no son un problema, etc., etc., etc.

Ahora solo uso bash para el más simple de los scripts.