6

私はスクリプトを書くのが初めてで、プログラムの出力を期待される出力に対して自動的にテストするbashスクリプトを開始する方法を理解するのに苦労しています。

対応する期待される出力out1、out2などに対して、テスト入力のセット(in1 in2など)で指定された実行可能ファイルを実行するbashスクリプトを記述し、それらが一致することを確認したいと思います。テストするファイルは、stdinから入力を読み取り、出力をstdoutに書き込みます。したがって、入力ファイルでテストプログラムを実行するには、I/Oリダイレクトが必要になります。

スクリプトは、テストされる実行可能ファイルの名前となる単一の引数で呼び出されます。

私はこれを始めるのに苦労しているので、どんな助けでも(私がこれを行う方法をさらに説明するリソースへのリンク)大いに感謝されます。私は明らかに自分自身を検索しようとしましたが、それではあまり成功していません。

ありがとう!

4

5 に答える 5

10

あなたが望むものを私が手に入れたら; これはあなたを始めるかもしれません:

bash と 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

編集。

終了コード チェックを追加しました。そして短いウォークトラフ:

これは要するに次のことを行います:

  1. 引数が指定されているかどうかを確認します (bin/application)
  2. 「ベース名」の配列を使用し、これをループして実際のファイル名を生成します。
    • すなわち:("file1" "file2")あなたが得る配列を持つ
      • ファイル内:file1.in
      • 検証する出力ファイル:file1.out
      • 出力ファイル:file1.out.tst
      • ファイル内:file2.in
      • ...
  3. stdinでアプリケーションを実行し、アプリケーション用に in ファイルにリダイレクトし、 でアプリケーションからファイル テストに<リダイレクトします。stdout>
  4. ie のようなツールを使用してdiff、それらが同じかどうかをテストします。
  5. ツールからの終了/戻りコードを確認し、メッセージを出力します (FAIL/OK)
  6. 続行を促します。

コース外のすべてを変更、削除などできます。


いくつかのリンク:

于 2012-04-12T07:07:15.500 に答える
2

Expectは、この種の問題に完全に適合する可能性があります。

Expect は主に、telnet、ftp、passwd、fsck、rlogin、tip などの対話型アプリケーションを自動化するためのツールです。Expect を使用すると、この作業が本当に簡単になります。Expect は、これらの同じアプリケーションのテストにも役立ちます。

于 2012-04-12T06:32:44.083 に答える
0

最初に、 I/O リダイレクションに関する Advanced Bash-Scripting Guide の章を見てください。

次に、なぜ bash スクリプトを使用するのかを尋ねなければなりません。メイクファイルから直接実行してください。

たとえば、次のようなものを含む一般的なメイクファイルがあります。

# 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

このように、必要な数のテストを追加できます。期待される出力を含むファイルに対して毎回出力ファイルを比較するだけです。

もちろん、これは実際にプログラムをビルドするためにメイクファイルを使用している場合にのみ関係します。:-)

于 2012-04-12T07:20:44.060 に答える
0

期待される出力は、2 番目の種類の入力です。

たとえば、二乗関数をテストする場合、入力は (0, 1, 2, -1, -2) のようになり、出力は (0, 1, 4, 1, 4) のようになります。

次に、入力のすべての結果を予想される出力と比較し、たとえばエラーを報告します。

配列を操作できます:

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

もちろん、ファイルから両方の配列を読み取ることができます。

(( ... )) を使用したテストでは、算術式、文字列、およびファイルを呼び出すことができます。試す

 help test 

概要については。

ファイルから単語単位で文字列を読み取る:

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

配列に読み込む:

arr=($(< file1)) 

ファイルを行単位で読み取ります。

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

プログラム出力に対するテストは、文字列比較とプログラム出力のキャプチャのように聞こえます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

さらに便利: [[ ... ]] ブラケット内の =~ を使用した文字列の正規表現マッチング:

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
于 2012-04-12T06:53:55.350 に答える