2012-04-12 15 views
6

Sono molto nuovo nella scrittura degli script e non riesco a capire come iniziare con uno script bash che testerà automaticamente l'output di un programma rispetto all'output previsto.Script Bash per testare automaticamente l'output del programma - C

Voglio scrivere uno script di bash che eseguirà un eseguibile specificato su una serie di input di test, ad esempio in1 in2 ecc., Rispetto ai corrispondenti output previsti, out1, out2, ecc. E verificare che corrispondano. Il file da test legge il suo input da stdin e scrive il suo output su stdout. Quindi l'esecuzione del programma di test su un file di input comporterà il reindirizzamento I/O.

Lo script verrà invocato con un singolo argomento, che sarà il nome del file eseguibile da testare.

Ho problemi ad andare avanti così, quindi qualsiasi aiuto (collegamenti a qualsiasi risorsa che spieghi ulteriormente come potrei farlo) sarebbe molto apprezzato. Ovviamente ho provato a cercare me stesso, ma in questo non ho avuto molto successo.

Grazie!

+1

È possibile utilizzare i comandi 'diff' o' cmp' per confrontare gli output. –

+0

I programmi 'diff',' cmp' e 'comm' (specialmente i primi due) sono usati per confrontare due file. Pertanto, è possibile acquisire l'output previsto in un file, l'output effettivo in un altro e quindi confrontare i file. Questo è il modo più semplice per farlo; non è necessariamente il migliore –

+0

Penso che la tua descrizione sia un po 'sbagliata. Il modo in cui l'ho letto, vuoi che gli ingressi corrispondano alle uscite. Ma penso che vuoi dire che hai ingressi di test, uscite effettive e uscite previste. E tu vuoi diff gli ultimi due. – Mikel

risposta

0

Funzioni. Herestrings. Reindirizzamento. Sostituzione del processo. diff -q. test.

2

Expect potrebbe essere una misura perfetta per questo tipo di problema:

Aspettatevi è uno strumento principalmente per l'automazione di applicazioni interattive come telnet, ftp, passwd, fsck, rlogin, punta, ecc Si aspettano davvero rende questa roba banale. Expect è utile anche per testare le stesse applicazioni .

0

risultati previsti sono un secondo tipo di ingresso.

Ad esempio, se si desidera testare una funzione quadrata, è necessario immettere come (0, 1, 2, -1, -2) e l'output previsto come (0, 1, 4, 1, 4).

Quindi confrontare ogni risultato di input con l'output previsto e segnalare errori ad esempio.

Si potrebbe lavorare con le matrici:

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 

Naturalmente si può leggere entrambi gli array da un file.

Il test con ((...)) può richiamare espressioni aritmetiche, stringhe e file. Prova

help test 

per una panoramica.

stringhe di lettura a parola da un file:

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

Leggi in un array:

arr=($(< file1)) 

Leggere il file formato da linee:

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

test contro il programma di uscita suona come confronto di stringhe e acquisizione dell'output del programma 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 

Ulteriori usesful: regolare l'espressione di corrispondenza su stringhe con = ~ tra parentesi quadre [[...]]:

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

Se ottengo ciò che si vuole; questo potrebbe farti iniziare:

Un mix di bash + strumenti esterni come 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 

Modifica.

Aggiunto controllo del codice di uscita; E una breve depressione passi:

Ciò a breve do:

  1. Verificare se l'argomento è dato (bin/applicazione)
  2. utilizzare un array di "nomi di base", ciclo di questo e generare i nomi dei file reali .
    • Ie: Avere serie ("file1" "file2") si ottiene
      • In File: file1.in
      • Out di file per convalidare contro: file1.out
      • Out File: file1.out.tst
      • In File: file2.in
      • . ..
  3. Esegui applicazione e reindirizzare in file per stdin per l'applicazione da <, e reindirizzare stdout dall'applicazione al file di test da >.
  4. Utilizzare uno strumento come ad esempio diff per verificare se sono uguali.
  5. Controllare il codice di uscita/ritorno dallo strumento e il messaggio di stampa (FAIL/OK)
  6. Richiesta di continuazione.

Qualsiasi e tutti fuori rotta possono essere modificati, rimossi ecc.


Alcuni link:

+0

Wow grazie mille! – Shabu

0

prima dare un'occhiata al capitolo avanzata di scripting Bash su I/O redirection.

Quindi devo chiedere Perché utilizzare uno script bash a tutti? Fallo direttamente dal tuo makefile.

Per esempio ho una contenente generic makefile qualcosa come:

# 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 

È possibile aggiungere il numero di prove che si desidera in questo modo. È sufficiente diffare il file di output ogni volta su un file contenente l'output previsto.

Naturalmente ciò è rilevante solo se si sta effettivamente utilizzando un makefile per la creazione del programma. :-)