Suponga que uno tiene un programa relativamente grande (digamos 900k SLOC en C #), todos comentados / documentados a fondo, bien organizados y funcionando bien. Todo el código base fue escrito por un único desarrollador senior que ya no está en la compañía. Todo el código se puede probar tal cual y se utiliza IoC en todo momento, excepto por alguna extraña razón por la que no escribieron ninguna prueba unitaria. Ahora, su empresa quiere ramificar el código y quiere que se agreguen pruebas unitarias para detectar cuándo los cambios rompen la funcionalidad principal.
- ¿Agregar pruebas es una buena idea?
- Si es así, ¿cómo podría uno comenzar con algo como esto?
EDITAR
Bien, entonces no esperaba respuestas con buenos argumentos para conclusiones opuestas. El problema puede estar fuera de mis manos de todos modos. También he leído las "preguntas duplicadas" y el consenso general es que "escribir exámenes es bueno" ... sí, pero no demasiado útil en este caso en particular.
No creo que esté solo aquí contemplando escribir pruebas para un sistema heredado. Voy a mantener métricas sobre cuánto tiempo se gasta y cuántas veces las nuevas pruebas detectan problemas (y cuántas veces no lo hacen). Volveré y actualizaré esto dentro de un año más o menos con mis resultados.
CONCLUSIÓN
Entonces resulta que es básicamente imposible agregar una prueba unitaria al código existente con cualquier apariencia de ortodoxia. Una vez que el código está funcionando, obviamente no puede iluminar en rojo / en verde sus pruebas, por lo general no está claro qué comportamientos son importantes para probar, no está claro por dónde comenzar y ciertamente no está claro cuando haya terminado. Realmente, incluso hacer esta pregunta pierde el punto principal de escribir pruebas en primer lugar. En la mayoría de los casos, encontré que en realidad era más fácil reescribir el código usando TDD que descifrar las funciones previstas y agregar retroactivamente pruebas unitarias. Al solucionar un problema o agregar una nueva característica, es una historia diferente, y creo que este es el momento de agregar pruebas unitarias (como algunos señalan a continuación). Con el tiempo, la mayoría del código se reescribe, a menudo antes de lo que cabría esperar, adoptando este enfoque.
fuente
Respuestas:
Si bien las pruebas son una buena idea, la intención era que el codificador original las construyera mientras creaba la aplicación para capturar su conocimiento de cómo se supone que funciona el código y qué puede romperse, lo que luego le habría sido transferido.
Al adoptar este enfoque, existe una alta probabilidad de que escriba las pruebas que tienen menos probabilidades de romperse, y se pierda la mayoría de los casos límite que se habrían descubierto al crear la aplicación.
El problema es que la mayor parte del valor provendrá de esas 'trampas' y situaciones menos obvias. Sin esas pruebas, el conjunto de pruebas pierde prácticamente toda su efectividad. Además, la compañía tendrá una falsa sensación de seguridad en torno a su aplicación, ya que no será significativamente más prueba de regresión.
Por lo general, la forma de manejar este tipo de base de código es escribir pruebas para el nuevo código y para la refactorización del código antiguo hasta que la base de código heredada se refactorice por completo.
También ver .
fuente
Sí, agregar pruebas es definitivamente una buena idea.
Dices que está bien documentado y eso te coloca en una buena posición. Intente crear pruebas utilizando esa documentación como guía, enfocándose en partes del sistema que son críticas o están sujetas a cambios frecuentes.
Inicialmente, el gran tamaño de la base de código probablemente parecerá abrumador en comparación con la pequeña cantidad de pruebas, pero no existe un enfoque de big bang, y comenzar en algún lugar es más importante que agonizar sobre cuál será el mejor enfoque.
Recomiendo el libro de Michael Feathers, Working Effectively with Legacy Code , para algunos consejos buenos y detallados.
fuente
No todas las pruebas unitarias tienen el mismo beneficio. El beneficio de una prueba unitaria se produce cuando falla. Cuanto menos probable es que falle, menos beneficioso es. Es más probable que el código nuevo o modificado recientemente contenga errores que el código que rara vez se cambia y que se prueba bien en producción. Por lo tanto, es más probable que las pruebas unitarias en código nuevo o modificado recientemente sean más beneficiosas.
No todas las pruebas unitarias tienen el mismo costo. Es mucho más fácil probar el código trivial que diseñó usted mismo hoy que el código complejo que alguien más diseñó hace mucho tiempo. Además, las pruebas durante el desarrollo generalmente ahorran tiempo de desarrollo. En el código heredado, ese ahorro de costos ya no está disponible.
En un mundo ideal, tendría todo el tiempo que necesita para probar el código heredado de la unidad, pero en el mundo real, en algún momento es lógico que los costos de agregar pruebas unitarias al código heredado superen los beneficios. El truco es identificar ese punto. Su control de versiones puede ayudar mostrándole el código que se modificó más recientemente y el que se modificó con más frecuencia, y puede comenzar poniéndolos bajo prueba unitaria. Además, cuando realice cambios en el futuro, coloque esos cambios y el código estrechamente relacionado bajo prueba unitaria.
Siguiendo ese método, eventualmente tendrá una cobertura bastante buena en las áreas más beneficiosas. Si, en cambio, pasa meses realizando pruebas unitarias antes de reanudar las actividades generadoras de ingresos, esa podría ser una decisión de mantenimiento de software deseable, pero es una pésima decisión comercial.
fuente
Absolutamente, aunque me resulta un poco difícil creer que el código esté limpio y funcione bien y que use técnicas modernas y simplemente no tenga pruebas unitarias. ¿Estás seguro de que no están sentados en una solución separada?
De todos modos, si vas a extender / mantener el código, las verdaderas pruebas unitarias son invaluables para ese proceso.
Un paso a la vez. Si no está familiarizado con las pruebas unitarias, aprenda un poco. Una vez que se sienta cómodo con los conceptos, elija una pequeña sección del código y escriba pruebas para ello. Luego el siguiente y el siguiente. La cobertura de código puede ayudarlo a encontrar lugares que se ha perdido.
Probablemente sea mejor elegir cosas peligrosas / arriesgadas / vitales para probar primero, pero puede ser más efectivo probar algo directo para comenzar primero, especialmente si usted / el equipo no está acostumbrado a la base de código y / o unidad pruebas.
fuente
Sí, tener pruebas es una buena idea. Ayudarán a documentar el código base existente que funciona según lo previsto y detectarán cualquier comportamiento inesperado. Incluso si las pruebas fallan inicialmente, déjelos y luego refactorice el código más tarde para que pasen y se comporten según lo previsto.
Comience a escribir pruebas para clases más pequeñas (las que no tienen dependencias y son relativamente simples) y pase a clases más grandes (las que tienen dependencias y son más complejas). Tomará mucho tiempo, pero sea paciente y persistente para que eventualmente pueda cubrir la base de código tanto como sea posible.
fuente
OK, voy a dar la opinión contraria ...
Agregar pruebas a un sistema de trabajo existente va a alterar ese sistema, a menos que sea así, todo el sistema está escrito con una burla en mente desde el principio. Lo dudo, aunque es muy posible que tenga una buena separación de todos los componentes con límites fácilmente definibles en los que puede deslizar sus interfaces simuladas. Pero si no es así, entonces tendrá que hacer cambios bastante significativos (en términos relativos) que pueden romper las cosas. En el mejor de los casos, pasará una gran cantidad de tiempo escribiendo estas pruebas, tiempo que podría emplearse mejor escribiendo una carga de documentos de diseño detallados, documentos de análisis de impacto o documentos de configuración de soluciones. Después de todo, ese es el trabajo que su jefe quiere hacer más que las pruebas unitarias. ¿No es así?
De todos modos, no agregaría ninguna prueba unitaria.
Me concentraría en herramientas de prueba externas y automatizadas que le brindarán una cobertura razonable sin cambiar nada. Entonces, cuando vengas a hacer modificaciones ... ahí es cuando puedes comenzar a agregar pruebas unitarias dentro de la base de código.
fuente
A menudo me he encontrado con esta situación, heredé una gran base de código sin una cobertura de prueba adecuada o nula, y ahora soy responsable de agregar funcionalidad, corregir errores, etc.
Mi consejo es asegurarse y probar lo que agrega, y si corrige errores o altera los casos de uso en el código actual, las pruebas de autor luego. Si tiene que tocar algo, escriba pruebas en ese punto.
Cuando esto se descompone es cuando el código existente no está bien estructurado para las pruebas unitarias, por lo que pasa mucho tiempo refactorizando para poder agregar pruebas para cambios menores.
fuente