2012-04-12 32 views
6

Soy muy nuevo en la escritura de scripts y tengo problemas para encontrar la manera de comenzar con un script bash que probará automáticamente el resultado de un programa contra el resultado esperado.Script Bash para probar automáticamente la salida del programa - C

Quiero escribir un script bash que ejecute un ejecutable especificado en un conjunto de entradas de prueba, digamos in1 in2 etc., contra salidas esperadas correspondientes, out1, out2, etc., y verifique que coincidan. El archivo que se probará lee su entrada de stdin y escribe su salida en stdout. Entonces, ejecutar el programa de prueba en un archivo de entrada implicará una redirección de E/S.

La secuencia de comandos se invocará con un único argumento, que será el nombre del archivo ejecutable que se probará.

Tengo problemas para ponerme en marcha, por lo que cualquier ayuda (enlaces a cualquier recurso que explique cómo podría hacerlo) sería muy apreciada. Obviamente he intentado buscarme pero no he tenido mucho éxito en eso.

Gracias!

+1

Puede usar los comandos 'diff' o' cmp' para comparar salidas. –

+0

Los programas 'diff',' cmp' y 'comm' (especialmente los dos primeros) se usan para comparar dos archivos. Entonces, puede capturar el resultado esperado en un archivo, el resultado real en otro, y luego comparar los archivos. Esta es la forma más simple de hacerlo; no es necesariamente lo mejor. –

+0

Creo que su descripción es un poco incorrecta. La forma en que lo leo, quiere que las entradas coincidan con las salidas. Pero creo que quiere decir que tiene entradas de prueba, productos reales y productos esperados. Y quieres diferenciar los dos últimos. – Mikel

Respuesta

0

Funciones. Herestrings. Redirección Sustitución de procesos diff -q. test.

2

Expect podría ser un ajuste perfecto para este tipo de problema:

esperar es principalmente una herramienta para automatizar aplicaciones interactivas como telnet, ftp, passwd, fsck, rlogin, punta, etc. esperar realmente hace que esto sea trivial. Esperar también es útil para probar estas mismas aplicaciones .

0

Las salidas esperadas son un segundo tipo de entrada.

Por ejemplo, si quiere probar una función cuadrada, tendría entrada como (0, 1, 2, -1, -2) y salida esperada como (0, 1, 4, 1, 4).

Luego compararía cada resultado de entrada con la salida esperada y reportaría errores por ejemplo.

Se podría trabajar con matrices:

in=(0 1 2 -1 -2) 
out=(0 1 4 2 4) 

for i in $(seq 0 $((${#in[@]}-1))) 
do 
    ((${in[i]} * ${in[i]} - ${out[i]})) && echo -n bad" " || echo -n fine" " 
    echo $i ": " ${in[i]}"² ?= " ${out[i]} 
done 

fine 0 : 0² ?= 0 
fine 1 : 1² ?= 1 
fine 2 : 2² ?= 4 
bad 3 : -1² ?= 2 
fine 4 : -2² ?= 4 

Por supuesto se puede leer ambas matrices desde un archivo.

Las pruebas con ((...)) pueden invocar expresiones aritméticas, cadenas y archivos. Pruebe

help test 

para tener una visión general.

cadenas de lectura WordWise desde un archivo:

for n in $(< f1); do echo $n "-" ; done 

Leer en una matriz:

arr=($(< file1)) 

Leer archivo linewise:

for i in $(seq 1 $(cat file1 | wc -l)) 
do 
    line=$(sed -n ${i}p file1) 
    echo $line"#" 
done 

Prueba contra el programa suena una salida como la comparación de cadenas y captura de la salida del programa n=$(cmd param1 param2):

asux:~/prompt > echo -e "foo\nbar\nbaz" 
foo 
bar 
baz 
asux:~/prompt > echo -e "foo\nbar\nbaz" > file 
asux:~/prompt > for i in $(seq 1 3); do line=$(sed -n ${i}p file); test "$line" = "bar" && echo match || echo fail ; done 
fail 
match 
fail 

Además usesful: regular la expresión juego de cuerdas con = ~ entre corchetes [[...]]:

for i in $(seq 1 3) 
do 
    line=$(sed -n ${i}p file) 
    echo -n $line 
    if [[ "$line" =~ ba. ]]; then 
    echo " "match 
    else echo " "fail 
    fi 
done 
foo fail 
bar match 
baz match 
8

Si consigo lo que quiere; esto podría comenzar:

Una combinación de bash + herramientas externas como diff.

#!/bin/bash 

# If number of arguments less then 1; print usage and exit 
if [ $# -lt 1 ]; then 
    printf "Usage: %s <application>\n" "$0" >&2 
    exit 1 
fi 

bin="$1"   # The application (from command arg) 
diff="diff -iad" # Diff command, or what ever 

# An array, do not have to declare it, but is supposedly faster 
declare -a file_base=("file1" "file2" "file3") 

# Loop the array 
for file in "${file_base[@]}"; do 
    # Padd file_base with suffixes 
    file_in="$file.in"    # The in file 
    file_out_val="$file.out"  # The out file to check against 
    file_out_tst="$file.out.tst" # The outfile from test application 

    # Validate infile exists (do the same for out validate file) 
    if [ ! -f "$file_in" ]; then 
     printf "In file %s is missing\n" "$file_in" 
     continue; 
    fi 
    if [ ! -f "$file_out_val" ]; then 
     printf "Validation file %s is missing\n" "$file_out_val" 
     continue; 
    fi 

    printf "Testing against %s\n" "$file_in" 

    # Run application, redirect in file to app, and output to out file 
    "./$bin" < "$file_in" > "$file_out_tst" 

    # Execute diff 
    $diff "$file_out_tst" "$file_out_val" 


    # Check exit code from previous command (ie diff) 
    # We need to add this to a variable else we can't print it 
    # as it will be changed by the if [ 
    # Iff not 0 then the files differ (at least with diff) 
    e_code=$? 
    if [ $e_code != 0 ]; then 
      printf "TEST FAIL : %d\n" "$e_code" 
    else 
      printf "TEST OK!\n" 
    fi 

    # Pause by prompt 
    read -p "Enter a to abort, anything else to continue: " input_data 
    # Iff input is "a" then abort 
    [ "$input_data" == "a" ] && break 

done 

# Clean exit with status 0 
exit 0 

Editar.

Se agregó la verificación del código de salida; Y una corta depresión de a pie:

Esto a su corta Do:

  1. Comprobar si el argumento es dado (bin/aplicación)
  2. utilizar una matriz de "nombres de base", bucle de esto y generar nombres de archivo reales .
    • Es decir: Tener gama ("file1" "file2") se obtiene
      • En archivo: file1.in
      • de salida de archivos para validar contra: file1.out
      • Ficha: file1.out.tst
      • En archivo: file2.in
      • . ..
  3. Ejecutar la aplicación y redirigir en el archivo de stdin para su aplicación por <, y redirigir stdout de la aplicación de la prueba del archivo por >.
  4. Utilice una herramienta como, por ejemplo, diff para comprobar si son iguales.
  5. Verificar el código de salida/retorno de la herramienta y el mensaje de impresión (FAIL/OK)
  6. Solicitar demora.

Cualquiera y todos los fuera de curso pueden ser modificados, eliminados, etc.


Algunos enlaces:

+0

¡Muchas gracias! – Shabu

0

Primero echar un vistazo a la Guía avanzada capítulo Bash-Scripting en I/O redirection.

Luego tengo que preguntar ¿Por qué usar un script bash en absoluto? Hágalo directamente desde su archivo MAKE.

Por ejemplo tengo una generic makefile que contiene algo como:

# type 'make test' to run a test. 
# for example this runs your program with jackjill.txt as input 
# and redirects the stdout to the file jackjill.out 
test: $(program_NAME) 
     ./$(program_NAME) <jackjill.txt> jackjill.out 
     ./diff -q jackjill.out jackjill.expected 

Puede añadir tantas pruebas como desee así. Simplemente difiere el archivo de salida cada vez contra un archivo que contiene su salida esperada.

Por supuesto, esto solo es relevante si realmente está usando un archivo MAKE para construir su programa. :-)

Cuestiones relacionadas