代码之家  ›  专栏  ›  技术社区  ›  Skilldrick

仅当测试通过时在Git中提交

  •  35
  • Skilldrick  · 技术社区  · 15 年前

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

    我想我需要用 pre-commit 在里面 /hooks ,而且我已经设法让它运行测试,但是如果测试失败,我似乎找不到停止提交的方法。我正在用 make test ,依次运行 python3.1 foo.py --test .不管测试通过还是失败,我似乎没有得到不同的退出条件,但我可能找错了地方。

    编辑: 这是我想在这里做的不寻常的事情吗?我本以为这是一个共同的要求…

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

    result = runner.run(allTests)
    if not result.wasSuccessful():
        sys.exit(1)
    
    3 回复  |  直到 9 年前
        1
  •  31
  •   Brian Campbell Dennis Williamson    15 年前

    我会检查以确保每一步,您的脚本在失败时返回一个非零的退出代码。检查您的 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 .如果 制作测试 是挂钩中的最后一个命令,因为最后一个命令的退出状态将是脚本的退出状态。但是如果你以后有支票 预提交 钩子,则需要确保退出时出错;否则,钩子末尾的成功命令将导致脚本退出,状态为 0 .

        2
  •  6
  •   VonC    15 年前

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

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

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

        3
  •  0
  •   skywinder Grady Player    9 年前

    另一个选项,如果不想手动处理预提交: 对于python、ruby等,有很好的工具来运行测试和语法检查: github/overcommit