使用makefile进行自动测试

使用makefile进行自动测试,makefile,Makefile,我对makefiles非常陌生,只是花了一整天的时间试图弄清楚如何自动化我的测试。对于这个项目,我有一个程序main.c,它接受输入和输出文件作为参数。输入文件的格式为“test-{filler}.txt”,因此示例文件可以是“test invalid opcode.txt”。输出文件的格式为“out-{filler}.txt”,因此它的格式为“out invalid opcode.txt”。然后我想将输出与保存在“correct-{filler}.txt”中的正确输出进行比较,因此这将是“co

我对makefiles非常陌生,只是花了一整天的时间试图弄清楚如何自动化我的测试。对于这个项目,我有一个程序main.c,它接受输入和输出文件作为参数。输入文件的格式为“test-{filler}.txt”,因此示例文件可以是“test invalid opcode.txt”。输出文件的格式为“out-{filler}.txt”,因此它的格式为“out invalid opcode.txt”。然后我想将输出与保存在“correct-{filler}.txt”中的正确输出进行比较,因此这将是“correct invalid opcode.txt”。因此,每个测试都有一个输入、输出和正确的输出。我想检查输出和正确的输出是否有任何差异,我想在前缀为“test-”的每个测试文件上运行它。我通读了很多makefile规范和很多不同的例子,但是我真的很困惑如何处理这个问题。任何帮助都将不胜感激

以下是我必须运行的一个测试:

CC=gcc
CFLAGS=-o

main.o: main.c
    $(CC) $(CFLAGS) main.o $<

.PHONY: test
test: main.o test-provided.txt test-out.cs
    ./program test-provided.txt test-out.txt
    diff -q test-out.txt out-provided.txt
CC=gcc
CFLAGS=-o
main.o:main.c
$(CC)$(CFLAGS)main.o$<
冒牌货:测试
测试:main.o test-provided.txt test-out.cs
./program test-provided.txt test-out.txt
diff-q test-out.txt out-provided.txt
我希望自动测试的布局是这样的

.PHONY: autotest
autotest: program
    $(foreach <file with "test-" prefix> run:
        main.o <test-name> <out-name>
        diff -q <correct-name> <out-name>
.PHONY:自动测试
自动测试:程序
$(每次运行:
梅因
diff-q
但我真的不知道如何去实现它

谢谢你,很抱歉我不能发布更多的代码。我尝试了很多不同的东西,但没有一个离得足够近,值得发布

编辑以显示工作最终版本:
程序:main.c
$(CC)$(CFLAGS)$a$<
测试输入:=$(通配符测试-*.txt)
.PHONY:autotest$(测试输入)
自动测试:$(测试输入)
$(测试输入):测试-%.txt:程序
回显'>out-$*.txt
./$<$@out-$*.txt
diff-q correct-$*.txt out-$*.txt

一般来说,在make中使用循环不是很“make-ish”。makefile是一种完全基于迭代和递归的语言,因此尝试在配方中进行“额外”迭代通常是多余的

如果您需要迭代某个对象,尤其是当该对象是文件时,您应该尝试利用make的目标/先决条件组织使用make。上面给出了一个算法:

$(foreach <file with "test-" prefix> run:
    main.o <test-name> <out-name>
    diff -q <correct-name> <out-name>
$(每次运行:
梅因
diff-q
这非常适合make的默认行为。要将其转换为makefile,您需要编写一条规则来调用循环的单个迭代,然后使用先决条件为所需的文件运行它。类似于以下内容:

TEST_INPUTS := $(wildcard test-*.txt)
.PHONY: autotest $(TEST_INPUTS)

autotest: $(TEST_INPUTS)

$(TEST_INPUTS): test-%.txt: program
        $< $@ test-out.txt
        diff -q test-out.txt out-$*.txt
TEST\u输入:=$(通配符测试-*.txt)
.PHONY:autotest$(测试输入)
自动测试:$(测试输入)
$(测试输入):测试-%.txt:程序
$<$@test-out.txt
diff-q test-out.txt out-$*.txt
这不仅更像make,而且还有其他优点:例如,您可以运行
make test provided.txt
,它将只运行一个测试而不是所有测试


您必须在这里使用非正常模式规则,因为
。虚假的
目标无法使用模式规则。

不要使用
make
foreach
在recepies中,使用
bash
for
。您可以看看我是如何在这里做类似的事情的。注意,
for
在所有要测试的文件中循环,然后en每个文件上都有一个
检查
程序运行,然后检查程序退出状态。您绝对不应该将您的程序命名为
main.o
.o
文件是一个目标文件,不能作为可执行文件运行。尽管您正在将其构建为可执行文件,因此它可以运行,并使用
.o
扩展名对其进行命名阅读您的makefile会让每个人都感到困惑。我上面的评论并不是为了解决任何问题。它只是一个风格上的评论。注意,您还需要更改配方中的名称。最好使用自动变量,如
$@
$。注意,
程序的规则在这里仍然是错误的:它仍然使用<配方中的code>main.o
。您应该将其更改为
$@
或至少更改为
program
。同样,我在这里的评论只与样式相关,不希望修复任何错误(尽管最后一个错误:它永远不会按原样创建文件
program
)。有关您遇到的问题的讨论,请参阅下面的答案。非常感谢您的回答。当我尝试运行此操作时,我得到了
make:Nothing to Do for
autotest'。我编辑了我的问题,以包含我现在尝试运行的代码。这意味着通配符函数返回空字符串。您真的这样做了吗在您的目录中有一些名为
test foo.txt
的ve文件?如果在shell提示符下运行
ls test-*.txt
,您将运行
make autotest
它是否打印任何内容?是的。它打印test-provided.txt test replicate label.txt test-unrecognized-label.txt test large offset.txt test-test-unrecognized-opcode.txt test out.tXT如果您在分配后的行中添加
$(info TEST\u INPUTS=$(TEST\u INPUTS))
,然后运行
make
为该值打印什么?您可能需要运行
/program
而不仅仅是
program
。您的
$路径中可能没有当前目录(这是一件好事,在
$PATH
中有
是一个安全漏洞)。所以使用
/$
TEST_INPUTS := $(wildcard test-*.txt)
.PHONY: autotest $(TEST_INPUTS)

autotest: $(TEST_INPUTS)

$(TEST_INPUTS): test-%.txt: program
        $< $@ test-out.txt
        diff -q test-out.txt out-$*.txt