2010-01-18 10 views
33

Recientemente comencé a usar git, y también comencé a probar la unidad (usando el módulo unittest de Python). Me gustaría ejecutar mis pruebas cada vez que me comprometa, y solo cometeré si pasan.Confirmar en git solo si pasan las pruebas

Supongo que necesito usar pre-commit en /hooks, y he logrado que ejecute las pruebas, pero parece que no puedo encontrar una manera de detener la confirmación si fallan las pruebas. Estoy ejecutando las pruebas con make test, que a su vez está ejecutando python3.1 foo.py --test. Parece que no obtengo una condición de salida diferente si las pruebas pasan o fallan, pero es posible que esté buscando en el lugar equivocado.

Editar: ¿Es esto algo poco común que quiero hacer aquí? Yo hubiera pensado que era un requisito común ...

Edit2: Sólo en caso de las personas no se molestan en leer los comentarios, el problema era que unittest.TextTestRunner no sale con que no sea cero condición, ya sea el conjunto de pruebas es exitoso o no. Para atraparlo, lo hice:

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

Preguntas recientes sobre SO llegado hasta la parte superior de las consultas de Google con bastante rapidez; y luego caer también rápidamente en el ranking. No es raro hacer una pregunta y 5 minutos después obtenerla como el éxito principal de Google; pero en una semana, puede ser más difícil encontrarlo. –

+0

@Brian Ah, es suficiente. No me di cuenta de que Google funcionaba así. – Skilldrick

+0

¿Su comando 'python3.1 foo.py --test' devuelve un estado de salida distinto de cero? ¿'Make' devuelve un estado de salida distinto de cero si lo ejecuta manualmente? ¿Y cuál es el contenido de su gancho 'pre-commit'? –

Respuesta

30

Revisaría para asegurarme de que en cada paso del camino, su secuencia de comandos devuelve un código de salida distinto de cero cuando falla. Verifique si su python3.1 foo.py --test devuelve un código de salida distinto de cero si falla una prueba. Compruebe para asegurarse de que su comando make test devuelva un código de salida distinto de cero. Y, por último, compruebe que su gancho pre-commit devuelve un código de salida distinto de cero en caso de error.

Puede verificar un código de salida distinto de cero agregando || echo $? al final de un comando; que imprimirá el código de salida si el comando falló.

El siguiente ejemplo funciona para mí (estoy redirigir stderr a /dev/null para evitar la inclusión de una salida muy extraño aquí):

$ 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 

Nota del || exit 1. Esto no es necesario si make test es el último comando en el gancho, ya que el estado de salida del último comando será el estado de salida del script. Pero si tiene controles posteriores en su gancho pre-commit, entonces debe asegurarse de salir con un error; de lo contrario, un comando exitoso al final del enganche hará que su script salga con un estado de 0.

+0

Muy interesante. +1 – VonC

+2

@Brian - Gracias. El problema fue que estaba ejecutando mis pruebas con 'unittest.TextTestRunner', que no sale con un estado distinto de cero. Tuve que hacer 'if not result.wasSuccessful(): sys.exit (1)'. – Skilldrick

+2

Otro problema aquí es que la prueba se ejecuta en la copia de trabajo de la revisión y no en etapas. Si siempre compromete todos sus cambios, esto no es un problema, pero si realiza confirmaciones parciales, es posible que las confirmaciones intermedias no pasen la prueba (Ver: [http://stackoverflow.com/questions/2412450/git-pre-commit] -hook-changed-added-files/3068990 # 3068990] – LarryH

6

Podría analizar el resultado de la sesión de pruebas de pitón y asegúrese de que para salir de su gancho pre-commit con un estado distinto de cero?

El gancho debe salir con un estado distinto de cero después de emitir un mensaje apropiado si quiere detener la confirmación.

Así que si su secuencia de comandos python no devuelve el estado adecuado por alguna razón, debe determinar ese estado directamente desde el pre-commit script de enlace.
Eso garantizaría que la confirmación no continúe si las pruebas fallaron.
(o puede llamar desde el gancho a un contenedor de Python que llamaría a las pruebas, y asegúrese de sys.exit(exit_status) según los resultados de la prueba).

+0

http://www.heikkitoivonen.net/blog/2009/01/28/pexpect-and-inconsistent-exit-status/ podría ser relevante también aquí – VonC

+2

Curiosamente, en el libro de Git, Scott Chacon hace una cosa similar (análisis los resultados de la prueba), con Ruby: http://book.git-scm.com/5_git_hooks.html – Skilldrick

+0

Gracias por su ayuda con esta. Tenía razón en que el problema era que no se devolvía el estado apropiado. Parte del problema son mis habilidades con el shell de noobish: todavía no me he acostumbrado. – Skilldrick

0

Otra opción, si usted no quiere manejar manualmente de pre-commit: Hay buena herramienta para ejecutar pruebas y comprobaciones de sintaxis para Python, Ruby y así sucesivamente: github/overcommit

Cuestiones relacionadas