Makeで単純な回帰テストフレームワークを実装するにはどうすればよいですか? (必要に応じて、GNU Makeを使用しています。)
私の現在のメイクファイルは次のようになります(簡単にするために編集されています)。
OBJS = jscheme.o utility.o model.o read.o eval.o print.o
%.o : %.c jscheme.h
gcc -c -o $@ $<
jscheme : $(OBJS)
gcc -o $@ $(OBJS)
.PHONY : clean
clean :
-rm -f jscheme $(OBJS)
例、「良い」式をテストするexpr.in
と「悪い」式をテストするunrecognized.in
のセットを用意します。それぞれに期待される出力はexpr.cmp
とunrecognized.cmp
です。手動テストは次のようになります。
$ jscheme < expr.in > expr.out 2>&1
$ jscheme < unrecognized.in > unrecognized.out 2>&1
$ diff -q expr.out expr.cmp # identical
$ diff -q unrecognized.out unrecognized.cmp
Files unrecognized.out and unrecognized.cmp differ
私はメイクファイルに次のような規則のセットを追加することを考えました:
TESTS = expr.test unrecognized.test
.PHONY test $(TESTS)
test : $(TESTS)
%.test : jscheme %.in %.cmp
jscheme < [something.in] > [something.out] 2>&1
diff -q [something.out] [something.cmp]
私の質問:
•[something]プレースホルダーには何を入れますか?
•diff
からのメッセージを「Test expr
failed」というメッセージで置き換える方法はありますか?
質問で述べられているように、あなたの元のアプローチが最善です。各テストは、予想される入力と出力のペアの形式です。 Makeはこれらを繰り返し処理してテストを実行することができます。 Shell for
ループを使用する必要はありません。実際、これを行うと、テストを並行して実行する機会が失われ、一時ファイル(不要なもの)をクリーンアップするための追加の作業が発生します。
これが解決策です(例として bc を使用):
Shell := /bin/bash
all-tests := $(addsuffix .test, $(basename $(wildcard *.test-in)))
.PHONY : test all %.test
BC := /usr/bin/bc
test : $(all-tests)
%.test : %.test-in %.test-cmp $(BC)
@$(BC) <$< 2>&1 | diff -q $(Word 2, $?) - >/dev/null || \
(echo "Test $@ failed" && exit 1)
all : test
@echo "Success, all tests passed."
このソリューションは、元の質問に直接対処します。
$<
と%.test-in
にそれぞれ対応する%.test-cmp
と$(Word 2, $?)
です。 @reinierpostコメントとは異なり、一時ファイルは必要ありません。echo
を使用して置き換えられます。make -k
で呼び出す必要があります。make -k all
は、すべてのテストが成功した場合にのみ実行されます。ファイルの命名規則(all-tests
)とファイル名のGNU make 関数を使用して*.test-in
変数を定義するときに、各テストを手動で列挙することを避けます 。ボーナスとして、これは、変数の長さがGNU makeで unlimited であるため、ソリューションがすぐに数万のテストにスケーリングすることを意味します。これは、オペレーティングシステム のコマンドライン制限 に到達するとフォールオーバーするシェルベースのソリューションよりも優れています。
テスト名を取得し、そこから入力ファイル名、出力ファイル名、smapleデータを推測するテストランナースクリプトを作成します。
#!/bin/sh
set -e
jscheme < $1.in > $1.out 2>&1
diff -q $1.out $1.cmp
次に、Makefile
で:
TESTS := expr unrecognised
.PHONY: test
test:
for test in $(TESTS); do bash test-runner.sh $$test || exit 1; done
automake
の- 簡単なテストフレームワーク のようなものを実装してみることもできます。
私が最終的に何をしたかは次のようになります:
TESTS = whitespace list boolean character \
literal fixnum string symbol quote
.PHONY: clean test
test: $(JSCHEME)
for t in $(TESTS); do \
$(JSCHEME) < test/$$t.ss > test/$$t.out 2>&1; \
diff test/$$t.out test/$$t.cmp > /dev/null || \
echo Test $$t failed >&2; \
done
ジャックケリーのアイデアに基づいており、ジョナサンレフラーのヒントが含まれています。
Diffについての質問だけを取り上げます。できるよ:
diff file1 file2>/dev/null ||エコーテスト何とか何とか失敗しました>&2
ただし、diffの代わりにcmpを使用することもできます。
別のメモでは、先に進んで思い切ってautomakeを使用すると役立つ場合があります。 Makefile.am(全体)は次のようになります。
bin_PROGRAMS = jscheme jscheme_SOURCES = jscheme.c utility.c model.c read.c eval.c print.c jscheme.h TESTS = test-script
かなりフル機能のテストフレームワークを含む、本当にたくさんの本当にいいターゲットが無料で手に入ります。