Hace poco más de un año tuve la suerte de poder tomarme un descanso de 9 meses en el trabajo. Decidí que en ese tiempo perfeccionaría mis habilidades de C #. Comencé a trabajar en un montón de proyectos y me obligué a seguir TDD.
Fue un proceso bastante esclarecedor.
Al principio fue difícil, pero con el tiempo aprendí a escribir código más comprobable (que, como resulta, tiende a ser un código más SÓLIDO) y en el proceso también agudicé mi habilidad de diseño OO.
Ahora estoy de vuelta en la fuerza laboral y estoy notando algo extraño.
Prefiero no seguir TDD.
Creo que TDD me ralentiza y en realidad hace que sea más difícil diseñar una aplicación limpia.
En cambio, he adoptado un enfoque ligeramente (masivo) diferente:
- Elige una porción vertical de trabajo
- Desarrollar un prototipo funcional.
- Refactorizar hasta que todo esté bien y ordenado
- Siéntese y aprecie el código maravillosamente SOLIDO y comprobable que he escrito.
Es posible que haya notado que el paso 1 no era "definir la superficie pública de mi objetivo de prueba" y el paso 2 no era "probar el bejesus fuera de dicha superficie pública". Es posible que también haya notado que ninguno de los pasos involucra pruebas. Estoy escribiendo código comprobable, pero no lo estoy probando ... todavía.
Ahora, me gustaría dejar en claro que en realidad no estoy renunciando a ningún tipo de prueba. El código que estoy escribiendo funciona . Funciona porque lo estoy probando manualmente.
También me gustaría dejar en claro que tampoco renunciaré a todas las pruebas automatizadas. Aquí es donde mi proceso es diferente. Y es por eso que hago esta pregunta.
TDD en teoría. No en la práctica.
Mi proceso ha evolucionado un poco y he logrado un equilibrio entre TDD y ninguna prueba que encuentro muy productiva y también razonablemente segura. Va de la siguiente manera:
- Implemente una porción de trabajo vertical que funcione con las pruebas en mente, pero no escriba ninguna prueba.
- Si en el futuro (por ejemplo, un mes después) ese segmento necesita modificación
- Escriba pruebas unitarias, pruebas de integración, pruebas de comportamiento, etc. que garanticen que la porción de trabajo sea correcta
- Modifica el código
- Si esa porción no necesita modificación,
- Hacer nada
Simplemente cambiando la carga de escribir pruebas desde antes de escribir el código hasta antes de modificar el código, he podido producir mucho más código de trabajo. Y, cuando llego a escribir pruebas, escribo muchas menos, pero cubro casi tanto terreno (mayor ROI).
Me gusta este proceso, pero me preocupa que no pueda escalar bien. Su éxito depende de que los desarrolladores sean diligentes al escribir pruebas antes de cambiar las cosas. Y eso parece un riesgo bastante grande. Pero, TDD tiene el mismo riesgo.
Entonces, ¿voy al infierno de [BT] DD, o esta es una forma común de codificación y prueba pragmática?
Me gustaría seguir trabajando de esta manera. ¿Qué puedo hacer para que este proceso funcione a largo plazo?
Nota:Soy el único desarrollador de mis proyectos y soy responsable de todo: recopilación de requisitos, diseño, arquitectura, pruebas, implementación, etc. Sospecho que es por eso que mi proceso está funcionando.
fuente
If that slice doesn't need modification
. lizkeogh.com/2012/06/24/beyond-test-driven-developmentRespuestas:
Para que el proceso funcione a largo plazo, escribiría las pruebas cuando se escriba el código.
Lo que puede parecer contradecir su enfoque. Sin embargo, ha formulado la pregunta, así que le daré mi opinión:
No tiene que escribir las pruebas antes del código. olvida esa pureza. Sin embargo, desea escribir las pruebas en ese momento.
Una vez que tiene el código funcionando, lo ha modificado un poco, ha solucionado algunos errores (estamos hablando de una escala de tiempo aquí), entonces está en un punto de máximo conocimiento sobre lo que está haciendo el código. Este es un buen momento para escribir pruebas que capturen su conocimiento.
Dejar esto hasta más tarde significa que el conocimiento (naturalmente) disminuirá con el tiempo.
También significa que si alguna vez te vas y alguien más se haga cargo de ti, no tendrás la deuda técnica inmediata de no haber documentado (a través de pruebas) qué hace qué.
Sobre todo, "algún día" puede no venir. Puede ser atropellado por un autobús o puede abordar el autobús para nuevas aventuras.
Finalmente, las pruebas manuales no escalan y con frecuencia no cubren todos los dispositivos utilizados por el usuario final.
fuente
Aunque TDD es difícil de implementar al 100%, hay un defecto en su enfoque
Implemente una porción de trabajo vertical que funcione
1.1 Pases de 1 año ...
1.2 Un nuevo desarrollador comienza a trabajar en el proyecto
Si esa porción necesita modificación
2.3 Nombres y parámetros del método de estilo Parse 'Clean Coding' 'GetUnicorn (colourOfUnicorn)'
2.4 Leer comentarios xml 'Obtiene un unicornio dorado (para montar) (obv)'
2.5 Caza al desarrollador original
2.6 Espero que recuerden lo que se supone que debe hacer el código
2.7 Haz que lo expliquen todo
Escriba Pruebas de Unidad, Pruebas de Integración, Pruebas de Comportamiento, etc. que esperemos que la porción de trabajo sea correcta
Creo que tiene razón al identificar que las pruebas unitarias realmente muestran su valor cuando se requieren modificaciones.
fuente
Estoy de acuerdo con Daniel Hollinrake y Ewan, en que el primer punto clave por el cual su prueba de solo si funciona bien hasta ahora es:
y que un segundo punto clave probable es:
No creo que TDD brinde un gran impulso de productividad para los programadores únicos, y puede que no mejore enormemente la calidad de su código si ya está escribiendo un código limpio y bueno.
Sin embargo, TDD seguramente mejorará la calidad del código de los programadores pobres / inexpertos / obsoletos, especialmente cuando llegue el momento de modificar el código sin romper nada más. Y aún más si la persona que modifica el código no es la misma persona que escribió el código originalmente o si han pasado varios meses en el medio.
En otras palabras, creo que TDD es una buena práctica para mejorar la calidad de su código (como se reconoce) pero también (y más importante) una especie de cobertura cuando trabaja con programadores promedio o mediocres (por ejemplo, de un departamento o una empresa diferente), que es una situación mucho más común que trabajar solo.
fuente
Para mí, lo clave parece ser esto:
Esto funciona para usted y está produciendo un código limpio y agradable (¡supongo!). Lo único que diría que debe hacer es crear un arnés de prueba para que otros desarrolladores puedan entrar y tener confianza en hacer cambios. Además, el arnés de prueba garantiza la coherencia en el comportamiento del código.
Creo que su enfoque es similar al mío. Por lo general, soy el único desarrollador de mis proyectos. Descubrí que la apreciación de TDD me ha permitido escribir funciones más pequeñas y un código más limpio, pero agrego pruebas mientras escribo el código como un arnés de prueba. De esa manera, a medida que el código evoluciona y la funcionalidad cambia, puedo estar razonablemente seguro de hacer cambios.
Una razón secundaria para escribir pruebas es que siento que son una forma de documentación. Pueden explicar mis razonamientos detrás de por qué se creó una función. Pero aquí, estoy pensando más en el desarrollo impulsado por el comportamiento.
fuente
Unit Testing se trata de abordar el problema de mantener el código. Si bien hay personas que dicen que son más rápidos escribiendo código con TDD en lugar de sin él, no me sorprende que pueda escribir más código nuevo sin escribir pruebas.
Los problemas que puedo ver con la práctica de escribir exámenes justo antes de cambiarlo:
A menudo necesito hacer cambios a toda prisa
Si bien puede ahorrar tiempo en general solo escribiendo pruebas cuando las necesita, no todo el tiempo es igual. Pasar 2 horas escribiendo pruebas para ahorrar 1 hora cuando estoy en modo de crisis, vale la pena.
Es más fácil escribir pruebas al mismo tiempo que escribo el código
Para escribir correctamente las pruebas unitarias, debe comprender el código que estoy probando. A menudo uso las pruebas unitarias como un ejercicio de comprensión, pero las pruebas unitarias del código existente pueden llevar mucho tiempo porque comprender el código existente lleva mucho tiempo. Compare eso con las pruebas de escritura a medida que escribe el código y lo encontrará mucho más rápido porque ya comprende el código: ¡simplemente lo escribió!
La definición del código heredado de Michael Feathers es código sin pruebas. Independientemente de si está de acuerdo con su definición, está claro que una parte sustancial del costo de modificar el código existente es asegurarse de que siga funcionando como se espera, a menudo ni siquiera está claro cuál es el comportamiento esperado.
Las pruebas de unidades de escritura compensan los costos al codificar una comprensión de cuál es el comportamiento correcto, así como también proporcionan una manera fácil para que el "futuro de nosotros" verifique que el comportamiento sigue siendo correcto.
fuente
Esta es una buena pregunta, y FWIW arrojaré mis dos centavos.
Hace aproximadamente un año, estaba codificando en Salesforce, una plataforma que tenía un mecanismo arraigado que lo obligaba a escribir no necesariamente pruebas antes de codificar , sino que lo obligaba a escribir pruebas en general.
La forma en que funcionó fue que el sistema lo obligaría a escribir pruebas, y haría un cálculo de la cantidad de líneas de su código que se probaron en un porcentaje. Si todo el código de su instancia de producción cayó por debajo del 75% probado, Salesforce no trabajará más.
El resultado final de esto fue que cada vez que hacía algo en Salesforce tenía que escribir o actualizar pruebas. Si bien estoy seguro de que esto tiene un gran impacto en la participación de mercado de Salesforce, en términos de la vida de un desarrollador , fue un dolor enorme en el culo .
La mayor parte del tiempo solo intentabas superar un pequeño ticket, y luego las pruebas llegan y duplican tu tiempo de desarrollo, para una característica que sabes que funciona.
Luego, el concepto incómodo de TDD se extendió por nuestro departamento, hasta nuestras bases de datos. Nuestros arquitectos querían realizar pruebas exhaustivas en todos los aspectos de nuestro departamento de TI. Ligero dolor en el culo, encuentro aún mayor dolor en el culo.
En aquel entonces, TDD nunca tuvo sentido para mí, e incluso ahora todavía no lo tiene. Gran parte de la funcionalidad que he escrito en mi rol actual tiene lugar en un mecanismo similar al que usted mencionó: en sectores verticales que refino hasta que funcionan. Cuando estaba en ese antiguo rol, y todavía ahora a menudo no sé qué va a hacer mi código hasta que lo escriba , así que la idea de que puedo escribir pruebas para conducir el código que voy a escribir solo. No tiene sentido para mí, es engorroso y, sobre todo, una pérdida de tiempo.
Dicho todo esto, las pruebas son cosas maravillosas y mágicas que hacen que todo esté bien en el mundo . Corrigen su código, se aseguran de que su aplicación haga lo que usted cree que hace y, en general, todo es más fluido. La pregunta entonces no es si escribe sus pruebas antes de codificar, o después de codificar, la pregunta es cuánto tiempo va a comprometerse a probar. Ese es el verdadero problema, al menos en mi experiencia de desarrollo de software. Las pruebas requieren tiempo y dinero, y debe hacerlo dentro del marco de intereses en competencia.
Entonces, en general, estoy de acuerdo con usted: TDD en la práctica es un poco incómodo y engorroso. En ese punto, debe tener en cuenta lo que funciona mejor en su situación actual . Si está escribiendo código crítico, solo asegúrese de que se pruebe en general. Si tiene tiempo, pruebe TDD y vea si agrega algo al proceso.
fuente
No podría recomendar su enfoque.
Si uso su enfoque sería, por ejemplo, como el siguiente (la casa es la aplicación):
Entonces, su enfoque cuesta mucho tiempo y mucho conocimiento antes de que yo construya la casa con su enfoque. ¡O lleva mucho tiempo! Además, no es agradable que Gentleman permita que otros escriban pruebas para su código cuando los requisitos hayan cambiado.
Entonces, hay un mejor enfoque sin programar un "prototipo" y comenzar a refactorizar. En lugar de programar un prototipo "haga un Diseño con UML de su Aplicación de la siguiente manera.
Claro que este enfoque también necesita algo de conocimiento en UML, pero es rápido de aprender. Y siempre es más rápido cambiar el nombre de una Clase o mover flechas en un digram que hacerlo en su IDE. Pero aprender el uso de marcos de prueba será más agotador al principio. Lo mejor está aquí para buscar pruebas de ejecución de proyectos de código abierto y ver cómo funcionan. Pero cuando tiene una aplicación de prueba, la próxima aplicación será mucho más rápida. Y creo que es una buena sensación saber que todo funciona bien.
Así que simplemente rechazo los enfoques porque requieren mucho tiempo para los principiantes y, después de todo, no son buenos. Para tener límites limpios entre su estructura y el comportamiento, puede usar el diseño impulsado por el dominio y, debajo de Organizar, el mismo dominio con dos paquetes (un paquete denominado estructura y el otro comportamiento denominado). También para tus pruebas. ejemplo simple mira este ejemplo escrito en java.
fuente
¿Probó manualmente cada rama posible de sus condiciones después de un pequeño cambio? Cuánto tiempo dura el ciclo de retroalimentación de sus pruebas manuales. Qué tan cerca del circuito de retroalimentación se obtiene con las pruebas automatizadas.
Las pruebas automatizadas (no importa la prueba primero o no) lo hacen ir rápido, al proporcionar un ciclo de retroalimentación más rápido en su código.
¿Está seguro de que recordará probar alguna condición manualmente después de seis meses? Por favor, no diga que documentará todas las condiciones importantes para probar, porque escribir un tipo de documentación / comentario es igual a escribir una prueba (documentación ejecutable)
Y de nuevo: durante la refactorización, ¿probó manualmente toda la lógica que se ve afectada por la refactorización? ¿Cuánto tiempo lleva probar el cambio de refactorización? Si la refactorización rompe algún código, ¿cuánto tiempo lleva encontrar una razón para los descansos?
El código hermoso y limpio que disfrutaste es muy subjetivo. Su código puede ser limpio y razonable para usted. El mejor método para verificar si su código es realmente legible, comprensible y comprobable son las pruebas y revisiones de código realizadas por otros desarrolladores.
Encontraste tu camino muy productivo solo porque solo eres desarrollador trabajando con el código y, creo, porque solo comenzaste a trabajar en este proyecto (¿Qué edad tiene este proyecto en 6 a 8 meses?).
Aún recuerda todo lo que escribió y puede reconocer una razón para posibles problemas. Estoy bastante seguro de que comenzará a escribir pruebas desde el principio después de 2 a 3 años de su proyecto, porque desea asegurarse de no olvidar nada.
fuente
Si nunca comete errores, realmente no necesita pruebas. La mayoría de los desarrolladores cometen errores, pero si nunca lo hace, y está seguro de que nunca cometerá errores en el futuro (y usted es el único en el proyecto), realmente no hay razón para perder el tiempo escribiendo pruebas.
Pero su solución está a mitad de camino porque está proponiendo escribir pruebas al cambiar el código, pero al mismo tiempo su método supone que nunca cometerá errores cuando decida para qué partes del código escribir pruebas. Esto solo funciona si siempre comprende perfectamente a qué áreas puede afectar un cambio. Creo que muchos desarrolladores comunes (¡no tú, por supuesto!) Han experimentado hacer un cambio, y luego una prueba en algún lugar inesperado falla, porque cometiste un error.
Of course good architecture, SOLID principles etc. should prevent this happening, but most developers are not perfect, and this is why tests across the system are valuable.
fuente