Tengo la tarea de obtener una aplicación heredada bajo prueba unitaria. Primero algunos antecedentes sobre la aplicación: es una base de código RCP Java Java de 600k LOC con estos problemas principales
- duplicación masiva de código
- sin encapsulación, se puede acceder a la mayoría de los datos privados desde el exterior, algunos de los datos de la empresa también se hicieron únicos, por lo que no solo se pueden cambiar desde el exterior, sino también desde cualquier lugar.
- sin abstracciones (por ejemplo, sin modelo comercial, los datos comerciales se almacenan en Object [] y double [] []), por lo que no hay OO.
Existe un buen conjunto de pruebas de regresión y un equipo de control de calidad eficiente está probando y encontrando errores. Conozco las técnicas para ponerlo a prueba en libros clásicos, por ejemplo, Michael Feathers, pero eso es demasiado lento. Como hay un sistema de prueba de regresión que funciona, no tengo miedo de refactorizar agresivamente el sistema para permitir que se escriban las pruebas unitarias.
¿Cómo debo comenzar a atacar el problema para obtener algo de cobertura rápidamente , de modo que pueda mostrar el progreso a la gerencia (y de hecho comenzar a ganar de la red de seguridad de las pruebas JUnit)? No quiero emplear herramientas para generar conjuntos de pruebas de regresión, por ejemplo, AgitarOne, porque estas pruebas no prueban si algo es correcto.
fuente
Respuestas:
Creo que hay dos ejes principales a lo largo de los cuales se puede colocar el código cuando se trata de introducir pruebas unitarias: A) ¿qué tan comprobable es el código? y B) ¿qué tan estable es (es decir, con qué urgencia necesita pruebas)? Mirando solo a los extremos, esto produce 4 categorías:
La categoría 1 es el lugar obvio para comenzar, donde puede obtener muchos beneficios con relativamente poco trabajo. La categoría 2 le permite mejorar rápidamente su estadística de cobertura (buena para la moral) y obtener más experiencia con la base de código, mientras que la categoría 3 es un trabajo más (a menudo frustrante) pero también produce más beneficios. Lo que debe hacer primero depende de la importancia de las estadísticas de moral y cobertura para usted. Probablemente no valga la pena molestarse en la categoría 4.
fuente
Tengo mucha experiencia trabajando en sistemas heredados (no Java), mucho más grande que esto. Odio ser portador de malas noticias, tu problema es el tamaño de tu problema. Sospecho que lo has subestimado.
Agregar pruebas de regresión al código heredado es un proceso lento y costoso. Muchos requisitos no están bien documentados: una corrección de errores aquí, un parche allí, y antes de que se dé cuenta, el software define su propio comportamiento. No tener pruebas significa que la implementación es todo lo que hay que pasar, no hay pruebas para "desafiar" los requisitos implícitos implementados en el código.
Si intenta obtener cobertura rápidamente, es probable que apresure el trabajo, lo hornee a medias y falle. Las pruebas proporcionarán una cobertura parcial de las cosas obvias y una cobertura deficiente o nula de los problemas reales. Usted convencerá a los mismos gerentes que está tratando de vender a esa Unidad de Pruebas que no vale la pena, que es solo otra bala de plata que no funciona.
En mi humilde opinión, el mejor enfoque es apuntar a las pruebas. Utilice las métricas, la intuición y los informes de registro de defectos para identificar el 1% o el 10% del código que produce la mayoría de los problemas. Golpea estos módulos con fuerza e ignora el resto. No intentes hacer demasiado, menos es más.
Un objetivo realista es "Desde que implementamos UT, la inserción de defectos en los módulos bajo prueba se ha reducido a x% de aquellos que no están bajo UT" (idealmente, x es un número <100).
fuente
Me recuerda ese dicho acerca de no preocuparse por la puerta del granero cuando el caballo ya se ha escapado.
La realidad es que realmente no hay una forma rentable de obtener una buena cobertura de prueba para un sistema heredado, ciertamente no en un corto período de tiempo. Como MattNz mencionó, será un proceso que llevará mucho tiempo y, en última instancia, será muy costoso. Mi instinto me dice que si intentas hacer algo para impresionar a la administración, es probable que crees una nueva pesadilla de mantenimiento al tratar de mostrar demasiado demasiado rápido, sin comprender completamente los requisitos que estás intentando probar.
Siendo realistas, una vez que ya ha escrito el código, es casi demasiado tarde para escribir las pruebas de manera efectiva sin el riesgo de perder algo vital. Por otro lado, se podría decir que algunas pruebas son mejores que ninguna, pero si ese es el caso, las pruebas mismas deben mostrar que agregan valor al sistema en su conjunto.
Mi sugerencia sería mirar esas áreas clave donde sientes que algo está "roto". Con eso quiero decir que podría ser un código terriblemente ineficiente, o que puedes demostrar que anteriormente era costoso de mantener. Documente los problemas, luego use esto como punto de partida para introducir un nivel de prueba que lo ayude a mejorar el sistema, sin embarcarse en un esfuerzo masivo de reingeniería. La idea aquí es evitar ponerse al día con las pruebas y, en su lugar, introducir pruebas para ayudarlo a resolver problemas específicos. Después de un período de tiempo, vea si puede medir y distinguir entre el costo anterior de mantener esa sección de código y los esfuerzos actuales con las correcciones que ha aplicado con sus pruebas de soporte.
Lo que debe recordar es que la administración está más interesada en el costo / beneficio y cómo eso afecta directamente a sus clientes y, en última instancia, a su presupuesto. Nunca están interesados en hacer algo simplemente porque es lo mejor que se puede hacer a menos que pueda demostrar que les proporcionará un beneficio que les interese. Si puede demostrar que está mejorando el sistema y obteniendo una buena cobertura de prueba para el trabajo que está haciendo actualmente, es más probable que la administración vea esto como una aplicación eficiente de sus esfuerzos. Esto podría permitirle argumentar el caso para extender sus esfuerzos a otras áreas clave, sin exigir una congelación completa del desarrollo del producto o, lo que es peor, ¡casi imposible argumentar a favor de reescribir!
fuente
Una forma de mejorar la cobertura es escribir más pruebas.
Otra forma es reducir la redundancia en su código, de tal manera que las pruebas existentes en efecto cubran el código redundante que actualmente no está cubierto.
Imagine que tiene 3 bloques de código, a, by b ', donde b' es un duplicado (copia exacta o casi incorrecta) de B, y que tiene cobertura en ayb pero no b 'con la prueba T.
Si refactoriza la base del código para eliminar b 'extrayendo la comunidad de b y b' como B, la base del código ahora se ve como a, b0, B, b'0, con b0 que contiene el código no compartido con b'0 y viceversa. viceversa, y tanto b0 como b'0 son mucho más pequeños que B e invocan / usan B.
Ahora la funcionalidad del programa no ha cambiado, y tampoco la prueba T, por lo que podemos ejecutar T nuevamente y esperar que pase. El código ahora cubierto es a, b0 y B, pero no b'0. La base del código se ha vuelto más pequeña (¡b'0 es más pequeña que b '!) Y aún cubrimos lo que cubrimos originalmente. Nuestro índice de cobertura ha aumentado.
Para hacer esto, necesita encontrar b, b 'e idealmente B para habilitar su refactorización. Nuestra herramienta CloneDR puede hacer esto para muchos idiomas, especialmente Java. Dices que tu código base tiene muchos códigos duplicados; Esta podría ser una buena manera de abordarlo en su beneficio.
Curiosamente, el acto de encontrar byb 'a menudo aumenta su vocabulario sobre las ideas abstractas que implementa el programa. Si bien la herramienta no tiene idea de lo que hacen byb ', el acto mismo de aislarlos del código, lo que permite un enfoque simple en el contenido de byb', a menudo les da a los programadores una muy buena idea de qué abstracción B_abstract implementa el código clonado . Por lo tanto, esto también mejora su comprensión del código. Asegúrate de darle un buen nombre a B cuando lo abstienes, y obtendrás una mejor cobertura de prueba y un programa más fácil de mantener.
fuente