实现`make check`或`make test`

如何使用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)
我想要进行一系列的回归测试,例如,
expr.in
测试一个“好”的表达&amp;
unrecognized.in
测试一个“坏”的,用
expr.cmp
&amp;
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]
我的问题: •我在[东西]占位符中添加了什么? •有没有办法用saying7ѭ替换消息说“测试
expr
失败”?     
已邀请:
如问题中所述,您最初的方法是最好的。您的每个测试都以一对预期输入和输出的形式出现。 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."
该解决方案直接解决您的原始问题: 您正在寻找的占位符分别为
$<
$(word 2, $?)
,分别对应先决条件
%.test-in
%.test-cmp
。与@reinierpost注释相反,不需要临时文件。 差异消息被隐藏并使用
echo
替换。 无论单个测试是否失败或成功,都应使用
make -k
调用makefile来运行所有测试。
make -k all
仅在所有测试成功时运行。 通过利用文件命名约定(
*.test-in
)和文件名的GNU make函数,我们避免在定义
all-tests
变量时手动枚举每个测试。作为奖励,这意味着解决方案可以扩展到数万个开箱即用的测试,因为GNU make中变量的长度是无限的。这比基于shell的解决方案更好,一旦达到操作系统命令行限制,该解决方案就会失败。     
制作一个测试运行器脚本,该脚本采用测试名称并推断输入文件名,输出文件名和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
这是基于杰克凯利的想法,包括Jonathan Leffler的提示。     
我会解决你关于差异的问题。你可以做: diff file1 file2&gt; / dev / null || echo test blah blah failed>&2 虽然您可能想使用cmp而不是diff。 另外,您可能会发现继续采取这样做很有帮助 暴跌并使用automake。你的Makefile.am(完整版) 看起来像: bin_PROGRAMS = jscheme jscheme_SOURCES = jscheme.c utility.c model.c read.c eval.c print.c jscheme.h TESTS =测试脚本 你会得到很多非常好的免费目标,包括一个功能齐全的测试框架。     

要回复问题请先登录注册