2012-04-12 6 views
6

Je commence à écrire des scripts et je n'arrive pas à comprendre comment démarrer un script bash qui testera automatiquement la sortie d'un programme par rapport à la sortie attendue. Je souhaite écrire un script bash qui exécutera un exécutable spécifié sur un ensemble d'entrées de test, par exemple in1 in2 etc., par rapport aux sorties attendues correspondantes, out1, out2, etc., et vérifier qu'elles correspondent. Le fichier à tester lit son entrée depuis stdin et écrit sa sortie sur stdout. L'exécution du programme de test sur un fichier d'entrée implique donc une redirection d'E/S.Script Bash pour tester automatiquement la sortie du programme - C

Le script sera appelé avec un seul argument, qui sera le nom du fichier exécutable à tester. J'ai des difficultés à démarrer, alors toute aide (liens vers des ressources expliquant comment je pourrais faire cela) serait grandement appréciée. J'ai évidemment essayé de me chercher mais je n'ai pas eu beaucoup de succès dans ça.

Merci!

+1

Vous pouvez utiliser les commandes 'diff' ou' cmp' pour comparer les sorties. –

+0

Les programmes 'diff',' cmp' et 'comm' (en particulier les deux premiers) sont utilisés pour comparer deux fichiers. Ainsi, vous pouvez capturer la sortie attendue dans un fichier, la sortie réelle dans un autre, puis comparer les fichiers. C'est la manière la plus simple de le faire; ce n'est pas forcément le meilleur. –

+0

Je pense que votre description est un peu faux. La façon dont je le lis, vous voulez que les entrées correspondent aux sorties. Mais je pense que vous voulez dire que vous avez des entrées de test, des sorties réelles et des sorties attendues. Et vous voulez différencier les deux derniers. – Mikel

Répondre

0

Fonctions. Herestrings. Redirection Substitution de processus diff -q. test.

2

Expect pourrait être un ajustement parfait pour ce genre de problème:

Attendez-vous est un outil principalement pour l'automatisation des applications interactives comme telnet, ftp, passwd, fsck, rlogin, conseil, etc. Attendez-vous vraiment rend ce truc trivial. Expect est également utile pour tester ces mêmes applications .

0

Les sorties attendues sont un deuxième type d'entrée. Par exemple, si vous voulez tester une fonction carrée, vous auriez une entrée comme (0, 1, 2, -1, -2) et une sortie attendue comme (0, 1, 4, 1, 4).

Ensuite, vous compareriez chaque résultat d'entrée à la sortie attendue et signaleriez les erreurs par exemple.

Vous pouvez travailler avec des tableaux:

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 

Bien sûr, vous pouvez lire les deux tableaux à partir d'un fichier. Test avec ((...)) peut invoquer des expressions arithmétiques, des chaînes et des fichiers. Essayez

help test 

pour un aperçu.

chaînes de lecture WordWise à partir d'un fichier:

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

Lire dans un tableau:

arr=($(< file1)) 

fichier Lire linewise:

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

Test contre les sons en programme comme comparaison de chaînes et capture de la sortie du programme 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 

De plus usesful: Expression régulière correspondant sur les chaînes avec = ~ dans [[...]] entre parenthèses:

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 je reçois ce que vous voulez; cela pourrait vous aider à démarrer:

Un mélange de bash + outils externes comme 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 

Modifier.

Vérification du code de sortie ajoutée; Et une courte creux à pied:

Cette volonté bref do:

  1. Vérifiez si l'argument est donné (bin /)
  2. Utilisez un tableau de « noms de base », boucle cela et générer des noms de fichiers réels .
    • Ie: tableau ayant ("file1" "file2") vous
      • Dans le fichier: file1.in
      • Out fichier pour validation: file1.out
      • Out fichier: file1.out.tst
      • Dans le fichier: file2.in
      • . ..
  3. Exécuter l'application et redirection dans le fichier à stdin pour l'application par < et rediriger stdout de l'application à tester de fichier par >. Utilisez un outil tel que diff pour tester si elles sont identiques.
  4. Vérifier le code de sortie/retour de l'outil et imprimer le message (FAIL/OK)
  5. Demander la continuité.

Tout et tout qui bien sûr peut être modifié, supprimé, etc.


Quelques liens:

+0

Wow, merci beaucoup! – Shabu

0

d'abord jeter un coup d'oeil au chapitre Guide d'écriture des scripts Bash avancé sur I/O redirection.

Puis-je demander Pourquoi utiliser un script bash? Faites-le directement depuis votre fichier makefile.

Par exemple j'ai un generic makefile contenant quelque chose comme:

# 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 

Vous pouvez ajouter autant de tests que vous voulez comme ça. Vous ne faites que comparer le fichier de sortie à chaque fois avec un fichier contenant votre sortie attendue.

Bien sûr, ceci n'est pertinent que si vous utilisez réellement un fichier makefile pour construire votre programme. :-)

Questions connexes