Obviamente, algunas aplicaciones antiguas no pueden ser o son extremadamente difíciles de probar unitarias debido a la forma en que fueron escritas en primer lugar.
Pero en algunos lugares, como algunos métodos auxiliares que probablemente podrían ser probados en unidades, ¿debería molestarme en escribir pruebas unitarias para ellos?
Quiero decir, podrían escribirse como un perro, pero por muy compleja que sea la lógica, la prueba del tiempo ha demostrado que funciona como debería. ¿Debería molestarme en hacer una prueba unitaria si digo que lo refactoriza o debo escribir pruebas unitarias para ellos siempre que tenga tiempo?
¿Hay algún valor en hacer esto?
Tenga en cuenta también que la definición del método puede ser vaga, y es posible que necesite investigar qué deberían hacer algunos de los métodos en determinadas condiciones.
fuente
Respuestas:
Creo que debería escribir tantas pruebas para la aplicación como sea posible. Lo ayudarán a aprender la base de código y lo prepararán para la refactorización o el nuevo desarrollo.
Hay algunos tipos de pruebas que puede escribir en ese escenario, cada una de ellas tiene sus propios méritos. Escribir estas pruebas te enseñará mucho sobre la aplicación con la que estás tratando.
En primer lugar, antes de comenzar a escribir pruebas de corrección, escriba pruebas que capturen el comportamiento actual , ya sea correcto o incorrecto. Es una apuesta bastante segura que descubrirá errores en los casos de esquina o en partes del código que no se probaron exhaustivamente al ejecutar el programa. No se preocupe por lo que debe hacer el código, simplemente capture lo que hace. A medida que avanza, no se preocupe por leer el código o pasar mucho tiempo averiguando cuál debería ser el resultado. Simplemente ejecute su prueba y capture esa salida en una afirmación.
Eso le dará una base sólida de comprensión de cómo funciona el código y dónde pueden estar los principales puntos débiles o áreas débiles. Si descubre errores, puede acercarse a las personas con el poder de decidir si vale la pena corregirlos o no y tomar esas decisiones.
A continuación, puede escribir algunas pruebas más grandes (en alcance) que cubran partes del código que pueden no ser fácilmente comprobables por unidad, pero donde aún sería importante probar los flujos de trabajo tanto como sea posible. Estas pruebas de flujo de trabajo o pruebas de integración , dependiendo de cómo desee verlas, le proporcionarán una buena base para refactorizar esos flujos de trabajo para hacerlos más verificables y protegerlo cuando se necesite agregar una nueva característica que pueda afectar un flujo de trabajo existente.
Con el tiempo, creará un conjunto de pruebas que estará allí para ayudarlo a usted o a la siguiente persona que termine heredando la aplicación.
fuente
Veo las pruebas unitarias como especificaciones, no simples pruebas. En el caso específico que ha mencionado, el valor real se obtendrá cuando realice una prueba unitaria antes de realizar cualquier cambio para cumplir con las nuevas especificaciones. Si va a cambiar el código heredado, entonces la mejor manera que veo es realizar pruebas unitarias para la funcionalidad, esto no solo traerá una red de seguridad sino que también nos ayudará a brindar más claridad sobre lo que hace esa unidad en particular. También puede obligarlo a hacer una investigación como la mencionó, lo cual es bueno para la comprensión. Por lo tanto, mi objetivo es obtener una prueba de unidad de módulo en su lugar antes de que esté a punto de sufrir un cambio.
fuente
NO . Según mi experiencia, existe una mala relación costo / beneficio para escribir pruebas unitarias después de que se escribió el código de producción porque es bastante improbable / difícil encontrar formas de probar el código de forma aislada sin una refactorización pesada. Uno de los beneficios del desarrollo conducido por pruebas es que obtienes código débilmente acoplado. Si escribe las pruebas después, hay muchas posibilidades de que el código esté estrechamente acoplado.
SÍ , podría escribir pruebas de integración para la aplicación para aquellas funciones en las que planea realizar cambios. De esta manera, puede hacer una prueba de regresión para ver si sus cambios rompen algo.
SÍ desde el punto de vista de la calidad y el desarrollador, es valioso tener pruebas.
NO desde el punto de vista comercial porque es muy difícil venderle al cliente que necesita tiempo / dinero para no obtener un valor comercial real, pero la vaga promesa de que los cambios comerciales no empeorarán las cosas.
fuente
Si es posible, hay aún más razones para escribir pruebas para el código existente que "ya funciona". Si no hay pruebas, lo más probable es que el código esté lleno de olores y podría necesitar una amplia refactorización para mejorar; El conjunto de pruebas lo ayudará a refactorizar. Incluso podría revelar que el código original no funciona correctamente; Recuerdo que una vez que escribí una prueba para un método que generaba un informe de ventas y descubrí que no estaba calculando las cosas correctamente, las ventas eran unos miles de dólares más de lo que realmente eran, y nadie había sabido en los cinco años que el código estaba en producción. (afortunadamente no fue el fin financiero real de las cosas, solo una estimación del informe de ventas).
Por supuesto, este consejo solo se aplica si realmente puede escribir las pruebas. En mi experiencia, una base de código sin pruebas es casi imposible de adaptar para las pruebas porque tendría que reescribir la mitad de los módulos de código para que sea lo suficientemente abstracto como para admitir las pruebas primero, y no podrá hacerlo.
fuente
Absolutamente sí , porque las pruebas unitarias no deberían verificar la corrección sino caracterizar el comportamiento real del sistema. Especialmente con un proyecto heredado, muchos de los requisitos están codificados implícitamente en el comportamiento real.
Esta caracterización sirve como línea de base de funcionalidad. Incluso si el comportamiento es incorrecto desde el punto de vista comercial, usted impide que el comportamiento se degrade más. Ganar tracción en un proyecto heredado puede ser difícil, y esto le brinda una línea de base para que pueda avanzar sin empeorar las cosas.
Entonces, escribe todas las pruebas unitarias que puedas. Para el código que no se puede probar, refactorice su código para separar las dependencias introduciendo "costuras" en el código, ubicaciones donde puede separar el código que desea probar del código que no desea probar.
Las ideas de las pruebas unitarias como pruebas de caracterización y costuras son los puntos principales en Trabajar eficazmente con código heredado de Michael Feathers, un libro que recomiendo encarecidamente.
fuente
He reflexionado sobre esto yo mismo, ya que hay un montón de documentos indocumentados muy mal escritos, pero que funcionan en nuestro sistema.
Usted hace un buen punto:
Si los requisitos cambian, creo que sería más valioso escribir las pruebas de unidades. Si no, no me molestaría especialmente, ya que no sería capaz de escribir las pruebas adecuadas, porque no conoce todas las condiciones.
Tienes tiempo cuando se prioriza, ¿verdad ?, así que nunca sucederá de todos modos. :)
fuente
¿Está tratando de aprovechar aspectos de esa base de código que no se han utilizado previamente en una aplicación de producción? Escriba pruebas unitarias para esos escenarios primero. Debe poder priorizar su trabajo aquí, y creo que The Art of Unit Testing tuvo algunos consejos al respecto (en particular, cómo abordar las pruebas de bases de código heredadas).
fuente
No asuma que todo funciona solo porque la aplicación está en funcionamiento ... por lo general, la "prueba del tiempo" solo muestra que a) aún no ha encontrado el resto de los defectos ob) las personas que han encontrado ellos no los han denunciado. (O tal vez ambos). Incluso el código que presumiblemente funciona ahora podría no funcionar la próxima vez que tenga que hacer un cambio.
Las pruebas unitarias le dan una medida de certeza de que cierta funcionalidad permanece intacta, a la vez que le proporciona una forma de demostrar esto para una cantidad razonable de casos. Eso es significativamente más valioso que "hurgar y probar esto", incluso para una única corrección de errores. (Escudriñar es más como el equivalente de las pruebas de integración o del sistema, por lo que, en ese sentido, probar manualmente la aplicación puede abarcar más de lo que pueden hacer las pruebas unitarias por sí solas, pero aún así es tiempo invertido de manera ineficiente. Incluso algún método para automatizar esas pruebas es mejor que hacerlo manualmente).
Definitivamente, debe escribir pruebas cuando cambie el código, ya sea reparando o refactorizando. Puede hacer bien en escribir las pruebas que pueda, si no es por otra razón que ahorrar algo de tiempo la próxima vez que tenga que arreglar un defecto (y habrá una próxima vez) ... aunque en este caso, usted Hay que equilibrar ese tiempo con las expectativas de las personas que pretenden que el software siempre está libre de defectos y, por lo tanto, se pierde el tiempo dedicado al mantenimiento futuro. (Sin embargo, eso no significa que deba ignorar los horarios actuales). En algún momento, si hace esto, tendrá suficiente cobertura para que pueda comenzar a demostrar el valor de las pruebas en aplicaciones heredadas, y eso podría ayudarlo a gastar ese tiempo en aplicaciones futuras, que eventualmente deberían liberar tiempo para gastar en desarrollo productivo.
fuente
Desde mi corazón de lala-land, diré que sí y no solo eso, sino que lo piratearé, refactorizaré y seguiré probando, pero asegúrese de no quedarse atrás en otros proyectos importantes. Como programador de trabajo, si su trabajo está en riesgo o si un gerente le dijo que tomara posesión, entonces sí. Si el equipo o la empresa pudieran sufrir, negocie con su gerente para informarle que es necesario hacer pruebas para evitar que la empresa se desplace. Si dice que no te preocupes, entonces estás fuera del gancho (no necesariamente, culpar a la delegación es una habilidad administrativa, así que asegúrate de estar fuera del gancho ... ¡en serio!)
¡Buena suerte!
fuente