39

我最近开始使用 git,也开始了单元测试(使用 Python 的unittest模块)。我想在每次提交时运行我的测试,并且只有在它们通过时才提交。

我猜我需要使用pre-commitin /hooks,并且我已经设法让它运行测试,但是如果测试失败,我似乎无法找到停止提交的方法。我正在运行测试make test,而后者又在运行python3.1 foo.py --test。无论测试通过还是失败,似乎我都没有得到不同的退出条件,但我可能找错了地方。

编辑:这是我想在这里做的不寻常的事情吗?我以为这是一个普遍的要求...

Edit2:以防人们懒得看评论,问题是unittest.TextTestRunner无论测试套件是否成功,它都不会以非零状态退出。为了抓住它,我做了:

result = runner.run(allTests)
if not result.wasSuccessful():
    sys.exit(1)
4

3 回答 3

33

我会检查以确保每一步,您的脚本在失败时返回一个非零退出代码。如果测试失败,请检查您是否python3.1 foo.py --test返回非零退出代码。检查以确保您的make test命令返回非零退出代码。最后,检查您的pre-commit钩子本身是否在失败时返回非零退出代码。

|| echo $?您可以通过添加到命令的末尾来检查非零退出代码;如果命令失败,它将打印出退出代码。

以下示例对我有用(我正在重定向 stderr/dev/null以避免在此处包含太多无关的输出):

$ python3.1 test.py 2>/dev/null || echo $?
1
$ make test 2>/dev/null || echo $?
python3.1 test.py
2
$ .git/hooks/pre-commit 2>/dev/null || echo $?
python3.1 test.py
1

test.py

import unittest

class TestFailure(unittest.TestCase):
    def testFail(self):
        assert(False)

if __name__ == '__main__':
    unittest.main()

Makefile

test:
    python3.1 test.py

.git/hooks/pre-commit

#!/bin/sh
make test || exit 1

注意|| exit 1. 如果是钩子中的最后一个命令,则这不是必需make test的,因为最后一个命令的退出状态将是脚本的退出状态。但是如果你稍后检查你的pre-commit钩子,那么你需要确保你退出时出错;否则,钩子末尾的成功命令将导致您的脚本以0.

于 2010-01-18T17:54:41.023 回答
6

您能否解析 python 测试会话的结果并确保以非零状态退出预提交挂钩?

如果钩子想要停止提交,它应该在发出适当的消息后以非零状态退出。

因此,如果您的 python 脚本由于任何原因没有返回适当的状态,您需要直接从pre-commit钩子脚本中确定该状态。
如果测试失败,这将确保提交不会继续。
(或者你可以从钩子中调用一个 python 包装器来调用测试,并sys.exit(exit_status)根据测试结果确保 a)。

于 2010-01-18T15:52:46.313 回答
0

另一种选择,如果您不想手动处理预提交:有一个很好的工具可以运行 Python、Ruby 等的测试和语法检查:github/overcommit

于 2015-05-19T09:18:13.467 回答