如何用Make实现一个简单的回归测试框架? (我正在使用 GNU Make,如果这很重要的话。)
我当前的 makefile 看起来像这样(为简单起见进行了编辑):
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)
我想要一组回归测试,e.g., 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
我想在 makefile 中添加一组规则,如下所示:
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
并附有一条消息:“测试expr
失败的”?
正如问题中所述,您原来的方法是最好的。您的每个测试都采用一对预期输入和输出的形式。 Make 非常有能力迭代这些并运行测试;无需使用 shellfor
环形。事实上,通过这样做,您将失去并行运行测试的机会,并且会为自己创建额外的工作以清理临时文件(不需要)。
这是一个解决方案(使用bc http://www.gnu.org/software/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."
该解决方案直接解决您原来的问题:
- 您正在寻找的占位符是
$<
and $(word 2, $?)
对应前提条件%.test-in
and %.test-cmp
分别。与 @reinierpost 评论相反,不需要临时文件。
- 差异消息被隐藏并替换为
echo
.
- 应使用以下命令调用 makefile
make -k
运行所有测试,无论单个测试是失败还是成功。
-
make -k all
仅当所有测试都成功时才会运行。
我们在定义时避免手动枚举每个测试all-tests
通过利用文件命名约定来变量(*.test-in
)和 GNU make文件名函数 https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html。作为奖励,这意味着解决方案可以扩展到开箱即用的数万个测试,因为变量的长度是无限 https://www.gnu.org/software/make/manual/html_node/Setting.html#Setting在 GNU make 中。这比基于 shell 的解决方案要好,后者一旦进入操作系统就会崩溃命令行限制 https://stackoverflow.com/questions/19354870/bash-command-line-and-input-limit.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)