Pregunta

Tenemos un sistema que tiene algunos scripts bash ejecutan además de código Java. Dado que estamos tratando de evaluar todo lo que podría romper Posiblemente, y los scripts bash puede romper, queremos probarlos.

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

¿Hay una manera o una mejor práctica para probar scripts bash? ¿O deberíamos dejar de usar secuencias de comandos bash y buscar soluciones alternativas que son comprobables?

¿Fue útil?

Solución 2

Me dio la siguiente respuesta de un grupo de discusión:

  

Es posible importar (incluye,   lo que sea) un procedimiento (función,   como quiera que se nombra) desde una externa   archivo. Esa es la clave para escribir una   script de pruebas: romper su   script en procedimientos independientes   que luego se pueden importar en tanto   la secuencia de comandos en ejecución y su prueba   guión, y luego tienes tu carrera   guión sea lo más simple posible.

Este método es como la inyección de dependencias para los scripts, y suena razonable. Evitar scripts bash y el uso de un lenguaje más comprobable y menos oscura es preferible.

Otros consejos

realidad, hay una shunit2 , un marco de prueba de unidad basado xUnit para secuencias de comandos shell basado Bourne. No he utilizado yo mismo, pero podría valer la pena echarle un vistazo.

preguntas similares se han preguntado antes:

TAP pruebas de Bash según norma: Sistema de prueba de Bash Automated

  

TAP, el Protocolo de prueba Cualquier cosa, es una sencilla interfaz basada en texto entre los módulos de prueba en un instrumento de prueba. TAP comenzó su vida como parte del instrumento de prueba para Perl, pero ahora tiene implementaciones en C, C ++, Python, PHP, Perl, Java, JavaScript, y otros.

epoxi es un marco de pruebas Bash he diseñado principalmente para probar otro software, pero lo uso para poner a prueba módulos de golpe, así, incluyendo y Carton .

Las principales ventajas son relativamente bajos gastos generales de codificación, anidación afirmación ilimitado y selección flexible de las afirmaciones de verificar.

Hice una presentación comparándolo con BeakerLib -. un marco utilizado por algunos de Red Hat

Nikita Sobolev escribió un excelente post comparando unos marcos de prueba diferente bash: aplicaciones de pruebas del golpe

Para los impacientes: la conclusión de Nikita era usar pero parece que Nikita se perdió el proyecto Batea-núcleo, que me parece que sea la de utilizar en el futuro como el proyecto los murciélagos originales no se ha mantenido activamente desde 2013.

¿Por qué dice que es "duro" para probar scripts bash?

¿Qué pasa con las envolturas de prueba como:

 #!/bin/bash
 set -e
 errors=0
 results=$($script_under_test $args<<ENDTSTDATA
 # inputs
 # go
 # here
 #
 ENDTSTDATA
 )
 [ "$?" -ne 0 ] || {
     echo "Test returned error code $?" 2>&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
 }

shell2junit , una utilidad para generar una salida de JUnit-como de las pruebas de escritura del golpe. Esto es útil porque el informe generado entonces puede ser leído por sistemas de integración continua, tales como los JUnit plug-ins para Jenkins y bambú.

Mientras shell2junit no proporciona el marco integral Bash scripting como shunit2 , sí permite tiene buena comunicación de los resultados de la prueba.

Trate bashtest . It `manera simple de probar sus scripts. Por ejemplo, usted tiene do-some-work.sh que cambian algunos archivos de configuración. Por ejemplo, añadir nueva PASSWORD = 'XXXXX' línea a config /etc/my.cfg archivo.

Usted escribe fiesta de línea de comandos de línea y luego comprueba la salida.

Instalar:

pip3 install bashtest

Crea pruebas es un sólo escribir comandos bash.

test-do-some-work.bashtest del archivo:

# 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

Puede encontrar algunos ejemplos aquí y aquí

Tal vez esto se puede utilizar, o contribuyó a

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

trataba de escribir los resultados en el protocolo TAP que imagino es bueno para CI, y bueno para los que quieren entornos de shell. Imagino algunas cosas ejecutar en los entornos de la cáscara así, algunos podrían argumentar se debe probar en su entorno shell.

darle una oportunidad 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 que ayude!

No puedo creer que nadie hablaba de OSHT ! Es compatible con ambos TAP y JUnit, es pura cáscara (es decir, no hay otras lenguas implicadas), que funciona de forma independiente también, y es simple y directa.

Las pruebas se parece a esto (fragmentos tomados de la página del proyecto):

#!/bin/bash
. osht.sh

# Optionally, indicate number of tests to safeguard against abnormal exits
PLAN 13

# Comparing stuff
IS $(whoami) != root
var="foobar"
IS "$var" =~ foo
ISNT "$var" == foo

# test(1)-based tests
OK -f /etc/passwd
NOK -w /etc/passwd

# Running stuff
# Check exit code
RUNS true
NRUNS false

# Check stdio/stdout/stderr
RUNS echo -e 'foo\nbar\nbaz'
GREP bar
OGREP bar
NEGREP . # verify empty

# diff output
DIFF <<EOF
foo
bar
baz
EOF

# TODO and SKIP
TODO RUNS false
SKIP test $(uname -s) == Darwin

Un simple ejecución:

$ bash test.sh
1..13
ok 1 - IS $(whoami) != root
ok 2 - IS "$var" =~ foo
ok 3 - ISNT "$var" == foo
ok 4 - OK -f /etc/passwd
ok 5 - NOK -w /etc/passwd
ok 6 - RUNS true
ok 7 - NRUNS false
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
ok 9 - GREP bar
ok 10 - OGREP bar
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
not ok 13 - TODO RUNS false # TODO Test Know to fail

La última prueba muestra como "no aceptable", pero el código de salida es 0 porque es un TODO. Uno puede establecer detallado así:

$ OSHT_VERBOSE=1 bash test.sh # Or -v
1..13
# dcsobral \!= root
ok 1 - IS $(whoami) != root
# foobar =\~ foo
ok 2 - IS "$var" =~ foo
# \! foobar == foo
ok 3 - ISNT "$var" == foo
# test -f /etc/passwd
ok 4 - OK -f /etc/passwd
# test \! -w /etc/passwd
ok 5 - NOK -w /etc/passwd
# RUNNING: true
# STATUS: 0
# STDIO <<EOM
# EOM
ok 6 - RUNS true
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
ok 7 - NRUNS false
# RUNNING: echo -e foo\\nbar\\nbaz
# STATUS: 0
# STDIO <<EOM
# foo
# bar
# baz
# EOM
ok 8 - RUNS echo -e 'foo\nbar\nbaz'
# grep -q bar
ok 9 - GREP bar
# grep -q bar
ok 10 - OGREP bar
# \! grep -q .
ok 11 - NEGREP . # verify empty
ok 12 - DIFF <<EOF
# RUNNING: false
# STATUS: 1
# STDIO <<EOM
# EOM
not ok 13 - TODO RUNS false # TODO Test Know to fail

Cambiar el nombre a utilizar una extensión .t y ponerlo en un subdirectorio t, y se puede utilizar prove(1) (parte de Perl) para ejecutarlo:

$ prove
t/test.t .. ok
All tests successful.
Files=1, Tests=13,  0 wallclock secs ( 0.03 usr  0.01 sys +  0.11 cusr  0.16 csys =  0.31 CPU)
Result: PASS

Conjunto OSHT_JUNIT o pasar -j para producir una salida de JUnit. JUnit también se puede combinar con prove(1).

He utilizado esta biblioteca ambas funciones de prueba a través del outsourcing sus archivos y luego ejecutar afirmaciones con IS / OK y sus negativos, y mediante el uso de secuencias de comandos RUN / NRUN. Para mí, este marco proporciona la mayor ganancia para los menos gastos generales.

shellspec porque quería un fácil de usar y una herramienta útil.

Es escrito por script de shell POSIX pura. Se ha probado con muchas conchas más que shunit2. Tiene características potentes que los murciélagos / murciélagos-núcleo.

Por ejemplo, soporte de bloque anidado, fácil burlarse / stub, fácil de omitir / pendiente, pruebas con parámetros, número de línea afirmación, ejecutar por número de línea, la ejecución en paralelo, la ejecución aleatoria, TAP / formateador JUnit, la cobertura y la integración CI, perfilador y etc.

Vea la demo en la página del proyecto.

He intentado muchas de las soluciones que se presentan aquí, pero pareció que la mayoría de ellos a voluminosos y difíciles de usar, por lo que he construido mi propio marco pocas pruebas: https://github.com/meonlol/t-bash

Es sólo un archivo en el repositorio que simplemente puede ejecutar directamente, con un conjunto básico de estilo JUnit afirma.

Lo he utilizado profesionalmente en varios proyectos internos y fueron capaces de hacer nuestros scripts bash muy estable y resistente a la regresión.

Es posible que desee echar un vistazo a bash_unit:

https://github.com/pgrange/bash_unit

Tome un vistazo a Outthentic , es simple, extensible por muchos idiomas (Perl, Python, Ruby, del golpe de la elección) y multiplataforma (Linux, Windows) marco para poner a prueba todas las aplicaciones de línea de comandos.

He encontrado que es difícil justificar el uso de fiesta para las escrituras más grandes cuando Python tiene tan enormes ventajas:

  • try / except permite escribir guiones más sólidos con la capacidad de deshacer los cambios en caso de error.
  • Usted no tiene que utilizar la sintaxis oscura como 'if [ x"$foo" = x"$bar"]; then ...' que es propenso a errores.
  • Fácil análisis de opciones y argumentos utilizando el módulo de getopt (y hay un módulo aún más fácil para analizar argumentos, pero el nombre no recuerdo).
  • Python le permite trabajar con listas / dicts y objetos en lugar de cadenas y matrices básicas.
  • El acceso a herramientas lingüísticas adecuadas, tales como expresiones regulares, bases de datos (seguro de que podría tubería todo en el comando mysql en bash, pero no es la mejor manera de escribir código).
  • No hay necesidad de preocuparse por el uso de la forma correcta del $* o "$*" o "$@" o $1 o "$1", espacios en los nombres de archivo no es un problema, etc, etc, etc.

Ahora sólo uso para la fiesta de la más simple de las secuencias de comandos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top