如何使用Makefile合并unittest结果?
我想用一个Makefile来运行单个测试文件,或者把所有测试合在一起运行,或者生成一个覆盖率报告。
我对Makefile还不是很熟悉,所以我借用了一个并进行了修改。结果可以在这里找到。
问题是,使用make test
命令时,它会一个接一个地运行每个测试,这样当测试很多时,很难看到哪些测试失败了,而且屏幕会滚动得很快。不过,我喜欢每个测试都在独立的进程中运行,这样它们之间不会互相干扰。
我的问题是:我能不能只用Makefile更好地合并结果,还是需要一个单独的脚本?你知道一些好的Makefile示例来运行测试吗?
(我只想使用Makefile + unittest + coverage,不想要其他依赖)
3 个回答
我有一个库目录,里面有几个子目录,每个子目录都有自己的单元测试。为了能一次性运行所有测试,我添加了以下测试目标:
test: $(addprefix test-,$(SUBDIRS))
test-%:
$(MAKE) -k --directory=$* test
这挺不错的,因为它可以在每个子目录中运行测试,而且可以通过比如说 make test -j5 来分发运行。不过,它有个问题。理想情况下,我希望能在所有目录中运行测试,而不管某个目录里的测试是否失败。我还想在最后能总结一下失败的情况,更重要的是,如果有一个或多个测试失败,能返回一个非零的退出代码。上面的代码可以运行所有测试,但它不会打印总结,也不会返回非零的退出状态。
下面是一些更复杂的代码,它能实现我想要的功能。不过,这段代码看起来不是很优雅:
clean_test:
rm -f testfailures
test: clean_test
$(MAKE) $(addprefix test-,$(SUBDIRS))
@echo "=== TEST SUMMARY ==="
@if [ -f $(BUILD_DIR)/testfailures ]; then \
echo "The following tests failed:"; \
cat $(BUILD_DIR)/testfailures; \
false; \
else \
echo "All tests passed."; \
fi
test-%:
$(MAKE) -k --directory=$* test || echo \
" $*" >> $(BUILD_DIR)/testfailures
另一种方法是使用unittest发现功能,这样可以把你所有的测试文件聚合到一起,一次性运行,比如在Makefile中。
test:
python -m unittest discover -p '*tests.py' -v
如果你觉得并行运行测试很重要,那就不要用unittest来运行测试,而是用nose或者pytest。这两个工具都有并行运行测试的选项。你应该可以在不修改测试代码的情况下做到这一点。
这里有一个简单的小技巧,你可以把它放到你的Makefile里,而不需要改动你的基础设施。
这个特殊的变量$?
会保存上一个命令的执行结果。通过使用它,你可以检查每个测试的返回值。在下面的脚本中,我统计了失败的测试数量,并在运行结束时输出这个数字。如果你想的话,也可以在一个测试失败时立即退出,这样就不用向上滚动查看输出了。
failed=0 \
for i in $(TESTS); \
do \
echo $$i; \
PYTHONPATH=$(GAEPATH):. $(PYTHON) -m tests.`basename $$i .py` $(FLAGS); \
if [ $? -ne 0 ] \
then \
$failed=$(($failed+1)) \
fi \
done \
if [$failed -ne 0] \
then \
echo $failed Tests Failed \
exit $failed \
fi \
当然,还有更好、更稳妥的测试方法,但这个小技巧如果你需要的话也能用。我建议你最终把下面的bash脚本转成python,这样你只需要运行./run_tests.py
就能执行所有的单元测试。因为python比bash更灵活,你可以更自由地解释和展示结果。根据你的需求,使用像unittest这样的单元测试框架可能会比自己写代码更好。