Estoy trabajando en el desarrollo de un antiguo proyecto escrito en Java. Tenemos más de 10 millones de LOC y, lo que es peor, más de 4000 pruebas funcionales.
Las pruebas, programadas por Hudson, están fallando como loco con cada cambio de código más grande. Verificación de la falla de la prueba: si se trata de un problema en el producto o en la prueba, lleva meses. ¡No podemos eliminar las pruebas anteriores porque no sabemos qué están probando!
¿Lo que podemos hacer? ¿Cómo proceder con tal cantidad de pruebas heredadas?
integration-tests
legacy-code
jenkins
Hector brosuli
fuente
fuente
Respuestas:
Abandónalos.
Sé que es difícil dejar de lado algo que claramente fue un gran esfuerzo de producción, pero las pruebas no están funcionando para ti, están trabajando en tu contra. Se supone que un conjunto de pruebas le dará la confianza de que el sistema hace lo que se supone que debe hacer. Si no lo hace, es un pasivo en lugar de un activo. No importa si el sistema o las pruebas tienen la culpa: mientras el conjunto de pruebas indique grandes cantidades de errores, no puede cumplir su propósito.
Lo que necesita ahora es un nuevo conjunto de pruebas que se ejecute sin errores. Eso significa que inicialmente tendrá poca cobertura, de hecho casi ninguna cobertura. Cada vez que arreglas o te tomas el tiempo para comprender a fondo algo sobre tu sistema, repasas ese conocimiento en una prueba. Con el tiempo, esto producirá una nueva red de seguridad en la que puede construir en el futuro. Tratar de reparar una red de seguridad vieja y mal entendida es una pérdida de tiempo que casi nunca vale la pena.
Incluso recomendaría que no se transfieran pruebas de la suite anterior a la nueva. Claro, algunos de ellos pueden tener éxito ahora, pero ¿es porque están probando exactamente lo que se supone que deben probar, o simplemente porque algunos disparos aleatorios siempre dan en el blanco? Obviamente, debe ser pragmático sobre lo que se puede y no se puede hacer con el esfuerzo que tiene disponible para gastar, pero no se puede comprometer el principio de que un conjunto de pruebas debe ejecutarse limpiamente para hacer su trabajo .
fuente
Ve y arregla las pruebas.
Su mayor error es que permitió que las pruebas fallaran, y obviamente lo ignoró por un tiempo. Lo que tiene no son "pruebas heredadas": está trabajando en un código heredado. Y considero que cada código escrito sin pruebas es heredado.
Parece que hay un problema aún mayor en su organización, ya que no está trabajando con requisitos claros. No puedo entender que usted (u otra persona) no pueda confirmar el comportamiento correcto.
fuente
Las pruebas son valiosas. Por lo menos, registran que alguien consideró que deberían pasar tiempo escribiéndolos, por lo que presumiblemente tuvieron algún valor para alguien una vez. Con suerte, contendrán un registro completo de todas las características y errores en los que el equipo ha trabajado alguna vez, aunque también pueden haber sido una forma de obtener algún número de cobertura de prueba arbitraria sin haber sido cuidadosamente pensados. Hasta que los mire, no sabrá cuál es el caso aquí.
Si la mayoría de sus pruebas pasan la mayor parte del tiempo, simplemente muerda la bala e invierta el tiempo en averiguar qué intentaban hacer las pocas pruebas que fallaron, y corregirlas o mejorarlas para que el trabajo sea más fácil la próxima vez. En ese caso, avance a la sección Determinar la intención de cada prueba , para obtener algunos consejos sobre qué hacer con un pequeño número de pruebas reprobadas.
Por otro lado, es posible que ahora se enfrente con una construcción Roja, y cientos o incluso miles de pruebas que no han pasado por un tiempo, y Jenkins no ha sido Verde durante mucho tiempo. En este punto, el estado de compilación de Jenkins se ha vuelto inútil, y un indicador clave de problemas con su registro ya no funciona. Necesita arreglar esto, pero no puede permitirse el lujo de detener todo el progreso hacia adelante mientras arregla el desorden en su sala de estar.
Para mantener su cordura mientras realiza la arqueología requerida para determinar qué valor se puede recuperar de las pruebas que han fallado, recomiendo los siguientes pasos:
Desactiva temporalmente las pruebas fallidas.
Hay varias formas de hacerlo, dependiendo de su entorno, que no describe claramente, por lo que no puedo recomendar ninguna en particular.
Algunos marcos apoyan la noción de fallas esperadas. Si el suyo lo hace, entonces esto es genial, ya que verá una cuenta regresiva de cuántas pruebas quedan en esta categoría, e incluso se le informará si algunas de ellas comienzan a pasar inesperadamente.
Algunos marcos admiten grupos de prueba y le permiten decirle a Hudson que solo ejecute algunas de las pruebas o que omita un grupo de pruebas. Esto significa que ocasionalmente puede ejecutar el grupo de prueba manualmente para ver si alguno está pasando.
Algunos frameworks le permiten anotar o marcar pruebas individuales para ser ignoradas. En este caso, es más difícil ejecutarlos como grupo, pero evita que te distraigan.
Puede mover las pruebas a un árbol de origen que normalmente no se incluye en la compilación.
In extremis, puede eliminar el código del HEAD del sistema de control de versiones, pero esto hará que sea más difícil de reconocer cuando se haya completado la tercera fase.
El objetivo es lograr que Jenkins se ponga verde lo antes posible, para que pueda comenzar a moverse en la dirección correcta lo antes posible.
Mantenga las pruebas relevantes.
Resuelva agregar nuevas pruebas a medida que agrega o modifica código, y comprométase a mantener todas las pruebas aprobadas.
Las pruebas pueden fallar por una variedad de razones, incluido el hecho de que no eran pruebas bien escritas para comenzar. Pero una vez que consigues que Jenkins sea verde, mantenerlo así es realmente importante.
Acostúmbrate a escribir buenas pruebas y haz que sea un gran problema si las pruebas comienzan a fallar.
Determine la intención de cada prueba.
Ir a través de las pruebas desactivadas una por una. Comience con los que afectan los módulos que cambia con más frecuencia. Determine la intención de la prueba y la razón del fracaso.
¿Prueba una función que se eliminó de la base del código a propósito? Entonces probablemente puedas eliminarlo.
¿Está atrapando un error que nadie ha notado todavía? Vuelva a instalar la prueba y corrija el error.
¿Está fallando porque estaba haciendo suposiciones injustificadas (por ejemplo, suponiendo que el texto del botón siempre estaría en inglés, pero ahora ha localizado su aplicación para varios idiomas)? Luego, descubra cómo hacer que la prueba se enfoque en una sola cosa y aislarla de los cambios no relacionados lo mejor que pueda.
¿La prueba se extiende por toda la aplicación y representa una prueba del sistema? Luego, retírelo del conjunto de pruebas principal de Jenkins y agréguelo al conjunto de Regresión que se ejecuta con menos frecuencia.
¿La arquitectura de la aplicación ha cambiado más allá del reconocimiento, por lo que la prueba ya no hace nada útil? Bórralo.
¿Se agregó la prueba para aumentar artificialmente las estadísticas de cobertura de código, pero en realidad no hace más que confirmar que el código se compila correctamente y no entra en un bucle infinito? O bien, ¿la prueba simplemente confirma que el marco de simulación seleccionado devuelve los resultados que acaba de decirle? Bórralo.
Como resultado de esto, algunas pruebas se mantendrán, algunas se modificarán, algunas se dividirán en múltiples fragmentos independientes de tamaño de bocado y algunas se eliminarán. Mientras sigas progresando con los nuevos requisitos, es responsable dedicar un poco de tiempo a lidiar con deudas técnicas como esta.
fuente
4000 pruebas es un problema insoluble. 40 pruebas es más manejable. Seleccione aleatoriamente un número manejable de pruebas para ejecutar y analizar. Clasifique los resultados como:
Si muchas de las pruebas caen en la primera categoría, puede ser hora de descartar su conjunto de pruebas actual y armar una útil para el código actual.
Si muchas de las pruebas fallan de una manera que le informa sobre un problema en su código, debe trabajar a través de las pruebas fallidas para solucionar los problemas. Puede encontrar que corregir uno o dos errores hace que se ejecute una gran cantidad de pruebas.
fuente
Si esta afirmación es cierta,
entonces eso implica que si regresa al código justo antes de un "cambio de código más grande", entonces muchas de las pruebas pasarán nuevamente. Después de hacer eso, tome una pequeña parte de los cambios y vea qué pruebas están fallando recientemente. Esto lo ayudará a aislar mejor qué cambios en el código están causando qué pruebas fallan. Para cada prueba, una vez que haya aislado el problema, debería poder determinar si el nuevo código tenía fallas o si la prueba lo era. Si es un problema con el nuevo código, asegúrese de compararlo con la última versión en caso de que ese error en particular ya se haya solucionado.
Repita hasta que tenga la última base de código.
Esto puede parecer una tarea abrumadora, pero es muy probable que una vez que siga este camino y comience a aislar algunos de los problemas, comenzará a surgir un patrón que puede acelerar enormemente el proceso. Por ejemplo:
fuente
Si no sabe lo que están probando, retírelos hasta que lo sepa. ¡Las pruebas son cosas fluidas, si elimina una función que ya no es necesaria, entonces debería esperar tener que cambiar la prueba que prueba esa función! Entonces, a menos que sepa lo que están probando las pruebas, no tiene la esperanza de cambiar la base de código con ellas.
Puede configurar el sistema de prueba en las máquinas del desarrollador y ejecutarlo allí para que los desarrolladores puedan ver con qué partes interactúan las pruebas, ojalá proporcionen esta documentación faltante y se familiaricen con la base de código que no está cambiando correctamente o no prueba más larga correctamente.
En resumen: si sus pruebas anteriores fallan cuando realiza cambios, los cambios en su código no son buenos. Use esas pruebas como un medio de educación sobre cómo funciona el sistema.
fuente
@Ignore
anotación de JUnit : puede mantener sus pruebas, pero no ejecutarlas. Entonces es simplemente una cuestión de volver a habilitarlos y arreglarlos uno a la vez. Le permite reducir su enfoque a un puñado de pruebas a la vez, en lugar de sentirse abrumado por miles de fallas.Lo más importante que haría es volver a los fundamentos de lo que se supone que deben hacer las pruebas y lo que la empresa necesita para seguir avanzando. El trabajo de las pruebas es identificar los problemas antes de que se vuelvan costosos de solucionar más adelante. Creo que la palabra clave en esa oración es "costosa". Estos problemas necesitan una solución comercial. ¿Aparecen problemas costosos en el campo? Si es así, las pruebas están fallando directamente.
Su gestión y usted deben realizar una verificación de la realidad. Usted está descubriendo que los costos de desarrollo se están disparando debido a un conjunto heredado de pruebas. ¿Cómo se comparan esos costos con los costos de entregar un producto defectuoso porque deshabilitó las pruebas? ¿Cómo se comparan con la tarea onerosa de descubrir qué comportamientos necesitan los usuarios (cuáles son las cosas que deben probarse)?
Estos son problemas que necesitan soluciones comerciales porque afectan el lado comercial del trabajo. Está entregando el producto a un cliente, y ese es un límite en el que la empresa está muy interesada. Pueden identificar soluciones que usted, como desarrollador, no puede. Por ejemplo, puede ser razonable para ellos proporcionar dos productos: un producto "heredado" para aquellos que necesitan confiabilidad y están dispuestos a renunciar a nuevas funciones, con un producto "visionario" que puede tener más fallas, pero es pionero en el futuro. Esto le daría la oportunidad de desarrollar dos conjuntos independientes de pruebas ... una heredada con 4000 pruebas y otra con más de las pruebas que cree que deben hacerse (y documentarlas para que este proceso no se repita).
Entonces, comienza el arte: ¿cómo puedes manejar a esta bestia de dos cabezas para que los avances en una rama también ayuden a la otra rama? ¿Cómo pueden sus actualizaciones a la rama "visonaria" regresar a la rama "heredada", a pesar de los estrictos requisitos de prueba? ¿Cómo pueden las continuas solicitudes de los clientes en la rama "heredada" moldear mejor su comprensión de los requisitos que necesitarían sus clientes heredados si finalmente volviera a fusionar los productos?
fuente
¡Es exactamente por eso que debes eliminar las pruebas anteriores! Si no sabes lo que están haciendo, entonces el fracaso no tiene sentido y ejecutarlos es una pérdida de tiempo. Tíralos y comienza de nuevo.
fuente