¿Alternativa al indicador de "aprobación / construcción defectuosa"?

14

Al tener una integración continua ejecutando las pruebas en cada confirmación, una práctica recomendada común es que todas las pruebas se aprueben en todo momento (también conocido como "no romper la compilación").

Encuentro algunos problemas con eso:

Por ejemplo, uno no puede ayudar a un proyecto de código abierto creando pruebas correspondientes a los tickets. Sé que si propongo una Solicitud de extracción a un proyecto de código abierto que contiene una prueba fallida, la construcción se marcará como fallida y el proyecto no querrá que se fusione en su repositorio porque "rompería la construcción".

Y No creo que sea malo tener pruebas fallidas en tu repositorio , es como tener problemas abiertos en tu rastreador. Estas son solo cosas que esperan ser reparadas.

Lo mismo ocurre en una empresa. Si trabaja con TDD, no puede escribir pruebas, confirmar y luego escribir el código lógico que cumple la prueba. Eso significa que si he escrito 4-5 pruebas en mi computadora portátil, no puedo realizarlas antes de irme de vacaciones. Nadie puede recuperar mi trabajo. Ni siquiera puedo "compartirlos" con un colega, excepto, por ejemplo, enviándolos por correo electrónico. También evita trabajar con una persona que escribe las pruebas, la otra que escribe el modelo.

Todo lo que puedo decir, ¿estoy haciendo un mal uso / malentendido del proceso de construcción / integración continua? Me parece que "pasar" / "no pasar" es un indicador demasiado estrecho.

¿Hay alguna manera de hacer que la integración continua y TDD sean compatibles?

¿Quizás hay una solución / práctica estándar para distinguir "nuevas pruebas" (que pueden fallar) y "pruebas de regresión" (que no fallan porque solían funcionar)?

    
pregunta Matthieu Napoli 08.02.2013 - 14:49

8 respuestas

12

Veo a dónde te diriges, pero este tipo de problemas normalmente se resuelven de otras maneras. Hay una buena razón por la que este es el protocolo estándar. Si alguien envía un código que no se compila, todos los que actualicen su código tendrán un programa que no compila . Eso incluye a los programadores que actualmente están trabajando en algo completamente diferente y de alguna manera se encuentran en una situación en la que deben esperar antes de poder compilar y probar en qué están trabajando.

El protocolo estándar es que puede realizar cambios incluso para un trabajo completo o incompleto, siempre que se compile para que los programadores puedan actualizar su código todos los días si es necesario.

Sin embargo, todavía veo a lo que te diriges. A veces desea comprometerse para simplemente guardar su código. Para esto, la mayoría de los repositorios de origen soportan la ramificación. Esto le permite crear una sucursal privada, trabajar en ella sin molestar a los demás, y luego unirse al tronco cuando se complete el trabajo. Esto le permite comprometerse cuando quiera sin ninguna de las reacciones negativas asociadas con la causa de que la compilación se rompa.

Si eso no es adecuado, GIT le permite comprometerse (empujar) a los repositorios en su máquina local, pero posiblemente el repositorio podría estar en cualquier lugar. Podría crear un repositorio para trabajos potencialmente parciales / incompletos y otro repositorio para trabajos terminados, y en ese repositorio puede agregar una compilación nocturna.

Una vez más, no puedo subrayar la importancia suficiente. ¡No cometas código roto en el tronco nunca! Tus contribuciones no pueden afectar el trabajo de otros programadores.

Editar

Veo que pretendías hacer pruebas rotas, pero en mi humilde opinión, hay poca diferencia. El objetivo de una prueba es determinar si un aspecto particular de un programa pasa o falla. Si siempre falla y usted no hace nada, entonces la prueba, en el uso tradicional de la prueba unitaria, no sirve para nada. Si lo usa para realizar alguna otra métrica que no necesariamente conlleve una confirmación "fallida" si una de esas pruebas falla, entonces le recomendaría encarecidamente que encuentre otra forma de hacer lo mismo.

De lo contrario, se arriesga a que la prueba nunca se tome en consideración o si causa que su compilación falle, que sus compañeros programadores ignoren las compilaciones fallidas. Es más importante que los programadores se den cuenta de cuándo rompieron una compilación que realizar una prueba que no ofrece información real y que solo puede dar lugar a malas prácticas.

    
respondido por el Neil 08.02.2013 - 15:00
4

Dada una rama maestra con pruebas fallidas, ¿cómo puede estar seguro, sin comparar esa lista con compilaciones anteriores, que no ha introducido errores?

Simplemente el seguimiento de la cantidad de pruebas fallidas es insuficiente: puede corregir una prueba y romper otra. Y si está de vacaciones, no quedará claro para los demás que observan la versión defectuosa.

Mantenga su sucursal maestra limpia y verde en todo momento. Trabajar en una rama. Mantenga la sucursal bajo IC, en un trabajo separado, y tenga pruebas fallidas al contenido de su corazón. Simplemente no rompas maestro.

Haga que el revisor de la sucursal solo fusione su sucursal si pasa todas las pruebas. (Más importante aún: ¡haga que el revisor solo pueda fusionar su rama si el resultado de fusionar la rama con el maestro pasa todas las pruebas!)

    
respondido por el Frank Shearar 08.02.2013 - 16:00
2

Hay formas de resolver sus problemas sin desechar prácticas bien entendidas y aceptadas sobre la integración continua.

Comenzaré con el problema de cometer una 'prueba rota' que corresponde a un ticket. Una solución es crear una o más pruebas de ruptura para exponer el problema, y luego solucionar el problema , para que puedan fusionarse de nuevo en la línea del código principal. La segunda solución es tener las pruebas rotas, pero usar algún tipo de indicador de ignorar para que realmente no se ejecuten y rompan la compilación. Posiblemente agregue un comentario o una anotación especial que haga muy obvio que esta es una prueba rota para Ticket#N . También adjunte una nota al boleto en sí que se refiera a las pruebas creadas que esperan ser sin marcar y ejecutarlas. Esto ayudaría a una persona a arreglar el boleto, pero tampoco sería una bandera roja para alguien que llega a la prueba.

Y en su próximo problema con TDD. TDD se trata de escribir una pequeña prueba y luego escribir una pequeña porción de código para hacer que la prueba pase . Luego sigue iterando hasta que tengas un pequeño módulo funcional. Siento que si escribes 4-5 pruebas, luego te vas de vacaciones, podrías estar haciendo las cosas mal. Puede emparejar el programa con alguien de manera que uno de ustedes escriba la prueba, el otro el código correspondiente. Sin embargo, no debe usar el repositorio de línea de código principal para compartir este código entre ustedes dos antes de que un módulo completado esté listo para ser confirmado. Como otros sugirieron, una rama compartida resolvería sus problemas allí.

Tratar de romper el mantra de integración continua puede llevar a caminos inesperados y aterradores. Por ejemplo, ¿qué significaría la cobertura de código en este tipo de entorno ? ¿Cómo no sentirían los desarrolladores que el sistema tiene muchas " Windows rota " ? ¿Cómo se podría hacer un cambio, ejecutar la prueba y saber si realmente están rompiendo algo nuevo, o solo es lo viejo?

    
respondido por el c_maker 09.02.2013 - 03:45
1

Creo que su problema fundamental es que está incluyendo RESULTADOS de prueba como parte de la compilación. Mientras que obviamente algunas personas están de acuerdo contigo, otras no. Romper la construcción se produce cuando no se construye. No cuando no se construye sin errores.

Considere un proyecto importante como Windows o Linux, o incluso algo como Firefox: ¿cree que se envían sin errores? Por supuesto no. Ahora, estos proyectos no están haciendo TDD, pero eso es realmente irrelevante: TDD no cambia dos hechos fundamentales: los errores existen y lleva tiempo corregirlos. El tiempo que un proyecto (fuente abierta o no) simplemente no puede permitirse perder en errores de baja prioridad. KDE recientemente tuvo un error que tenía más de una década arreglado. ¿Cuándo fue la última vez que escuchó a alguien decir "Me alegro de haber esperado una década para enviar nuestro proyecto"?

TDD, en cierto modo, probablemente lo hace MÁS FÁCIL de enviar con errores, porque tiene una mejor comprensión de lo que es la falla. Si puede definir con precisión qué causa el error, tiene una base excelente para sopesar el costo de solucionarlo.

Mi recomendación es encontrar un proyecto al que no le importe el rojo entre el verde.

    
respondido por el jmoreno 09.02.2013 - 07:40
1
 > a common best practice is to have all the tests passing (green) at all times.

Prefiero que todas las pruebas no fallen (no en rojo).

Con esta definición ligeramente diferente también puede definir pruebas que sean

  • aún no implementado (en gris en nunit si hay una NotImplementedException)
  • se sabe que está fallando="necesita hacer" marcando / anotando la prueba como ignorada (amarillo)

Si comprueba estos en el repositorio, su compilación continua no está rota y, por lo tanto, es válida.

    
respondido por el k3b 09.02.2013 - 12:34
0

Podrías considerar dos "conceptos" de compilación de CI diferentes.

  1. Compilaciones de CI regulares. La compilación de CI regular debe compilar y ejecutar solo aquellas pruebas para las cuales se ha escrito el código para hacerlas aprobar, de modo que los informes de CI de aprobaciones / fallas de prueba sean un indicador claro e inequívoco de regresión contra el estado previamente aceptado del código.
  2. Una compilación "futura" de CI. Esta compilación compila y ejecuta solo aquellas pruebas para las que no se ha escrito ningún código específicamente para hacerlas aprobar. Puede haber varias razones para tener tal prueba:

    • Se pueden agregar pruebas para casos de fallas específicas desde el rastreador de problemas, para los cuales aún no se ha intentado una solución. Es claramente útil ya tener una prueba de ejecución codificada para un problema, incluso sin una solución.

    • Pruebas agregadas para la nueva funcionalidad requerida que aún no se ha implementado.

    • A menudo es más fácil saber cómo probar una falla o característica que saber cómo implementar la característica o solución, y separar los dos pasos al realizar la prueba en el control de origen puede ser útil para asegurar que no se pierda información .

Al igual que en el CI "estándar", en el régimen de desarrollo regular, el equipo solo estaría mirando los resultados de compilación diarios de la compilación regular.

El equipo también puede vigilar la evolución de los casos de prueba de la compilación de CI "futura"; específicamente, para ver si algún cambio realizado para la CI normal soluciona los problemas de la compilación "futura", lo que puede ser una indicación de un importante problema subyacente o mejora del diseño.

Finalmente, si un miembro del equipo tiene más tiempo en sus manos, podría echarle un vistazo a solucionar uno de los problemas del "futuro", y si lo logra, migrelo a "regular" (mientras actualiza el estado del rastreador de problemas).

    
respondido por el Joris Timmermans 08.02.2013 - 17:29
0
  

Y no creo que sea malo tener pruebas fallidas en tu repo, es como tener problemas abiertos en tu rastreador. Estas son solo cosas que esperan ser reparadas.

El problema no es fallar las pruebas, es un indicador de regresión simple y sin contexto. Aka: como desarrollador, ¿puedo verificar un solo indicador y saber si introduje una regresión o un código de ruptura?

En el momento en que introduce el concepto de fallas "blandas" (está bien, estamos trabajando en él / aún no implementado / estamos esperando la nueva versión / se pasará de nuevo una vez que se arregle esta otra versión) , necesita que todos los que se ejecuten o miren la prueba para conocer el estado esperado. Lo que en un equipo lo suficientemente grande cambiará por hora: su indicador pierde sentido. En un contexto más pequeño (prueba de integración privada del equipo, por ejemplo), entonces creo que es como una deuda técnica y está bien, solo necesita ser administrado.

La forma en que la dirección de la mayoría de las herramientas es que 'verde / pasando' refleja el resultado esperado, no es que el código funcione:

  • Fitness tiene el concepto de falla esperada.
  • JUnit tiene @Ignored / @Test (expect =)
  • El pepino tiene el estado 'aún no implementado' (o como se llame)

Los que vienen con sus propios problemas (cómo se distingue entre 'sí, sabemos que está roto, trabajando en ello' y 'el comportamiento correcto es una excepción'), pero ayudan.

    
respondido por el ptyx 09.02.2013 - 17:26
0

Yo uso las pruebas omitidas.

En el marco de pruebas de unidad en particular que uso, puedo generar una excepción SkipTest. La prueba no se ejecuta en realidad, y su falla no interrumpirá la compilación. Sin embargo, puedo ver la cantidad de pruebas omitidas y ver si hay trabajo por hacer en esa área.

    
respondido por el Winston Ewert 21.02.2013 - 01:57

Lea otras preguntas en las etiquetas