Записывать в git, только если тесты пройдены - PullRequest
35 голосов
/ 18 января 2010

Я недавно начал использовать git, а также начал модульное тестирование (с помощью модуля unittest Python).Я хотел бы запускать свои тесты каждый раз, когда я фиксирую, и только если они проходят.

Я предполагаю, что мне нужно использовать pre-commit в /hooks, и мне удалось сделать этозапустить тесты, но я не могу найти способ остановить коммит, если они не пройдут тест.Я запускаю тесты с make test, который, в свою очередь, запускает python3.1 foo.py --test.Кажется, что я не получаю другое условие выхода, независимо от того, пройдены тесты или нет, но я могу искать не в том месте.делать здесь?Я бы подумал, что это общее требование ...

Edit2: На всякий случай, если люди не удосужились прочитать комментарии, проблема заключалась в том, что unittest.TextTestRunner незавершить работу с ненулевым статусом, независимо от того, был ли набор тестов успешным или нет.Чтобы поймать это, я сделал:

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

Ответы [ 3 ]

31 голосов
/ 18 января 2010

Я бы проверил, чтобы на каждом этапе ваш скрипт возвращал ненулевой код завершения при ошибке.Проверьте, не возвращает ли ваш 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.

6 голосов
/ 18 января 2010

Не могли бы вы проанализировать результат сеанса тестирования Python и убедиться, что выход из ловушки перед фиксацией имеет ненулевое состояние?

Хук должен выйти с ненулевым статусом после выдачи соответствующего сообщения, если он хочет остановить коммит.

Так что, если ваш скрипт на python по какой-либо причине не возвращает соответствующий статус, вам нужно определить этот статус непосредственно из pre-commit hook-скрипта.
Это гарантирует, что коммит не будет продолжен, если тесты не пройдены.
(или вы можете вызвать из ловушки оболочку Python, которая будет вызывать тесты, и обеспечить sys.exit(exit_status) в соответствии с результатами теста).

0 голосов
/ 19 мая 2015

Другой вариант, если вы не хотите обрабатывать вручную предварительную фиксацию: Есть хороший инструмент для запуска тестов и проверки синтаксиса для Python, Ruby и так далее: github / overcommit

...