¿Cuál es el lado negativo de su experiencia TDD? ¿Le parecen molestos e inútiles los pequeños pasos (la solución más simple para hacer que la prueba sea verde)? ¿Encuentra pruebas sin valor (cuando la prueba tiene sentido inicialmente pero en la implementación final verifica la misma lógica que otras pruebas)? etc.
Las preguntas anteriores son sobre cosas con las que me siento incómodo durante mi experiencia TDD. Por lo tanto, me interesa saber si otros desarrolladores tienen sentimientos similares y qué piensan de ellos.
Agradecería los enlaces a los artículos que describen los lados negativos de TDD (Google se llena de artículos positivos y a menudo fanáticos).
Respuestas:
Como todo lo que viene bajo el lema "Agile", TDD es algo que suena bien en teoría, pero en la práctica no está tan claro qué tan bueno es (y también como la mayoría de las cosas "Agile", se le dice que si no lo hace me gusta, lo estás haciendo mal).
La definición de TDD no está grabada en piedra: los tipos como Kent Beck exigen que se escriba una prueba que no se compila antes de una sola línea de código y cada línea de código se debe escribir para aprobar una prueba fallida. El diseño inicial es mínimo y todo se manejapor las pruebas. Simplemente no funciona. He visto una gran aplicación empresarial desarrollada utilizando esa metodología y espero que sea el peor código que veo en mi carrera (no estará muy lejos; y eso fue a pesar de tener algunos desarrolladores talentosos trabajando en ello). Por lo que he visto, da como resultado una gran cantidad de pruebas mal pensadas que validan principalmente que ocurren llamadas a funciones, que se lanzan excepciones cuando las variables son nulas y el marco burlón obtiene un entrenamiento completo (whoop-de-whoop); su código de producción se acopla mucho a estas pruebas y el sueño de una refactorización constante y fácil no aparece; de hecho, las personas son aún menos propensas a corregir un código incorrecto debido a todas las pruebas que se romperán.
Por el contrario, he oído a personas argumentar que TDD significa diseñar las pruebas por adelantado en un alto nivel como parte de la fase de planificación, junto con el diseño arquitectónico. Estas pruebas pueden cambiar durante el desarrollo a medida que hay más información disponible, pero se han considerado cuidadosamente y ofrecen una buena guía sobre lo que el código debería hacer realmente. Para mí eso tiene mucho sentido.
fuente
Esta ( autor de Clojure ) entrevista de Rich Hickey contiene lo siguiente. Me siento 100% comprensivo:
Otra declaración similar de Donald Knuth en la entrevista del libro Coders at Work , copiada y pegada desde aquí :
fuente
Mi experiencia negativa con TDD fue la primera. TDD sonó genial para mí, había hecho control de calidad durante años y todavía tenía los horrores frescos en mi mente. Quería eliminar todos los errores antes de que se convirtiera en una compilación. Desafortunadamente, usar TDD no garantiza que escribirás buenas pruebas. De hecho, mi predisposición inicial era escribir pruebas simples que generaran código simple. Código realmente simple que contenía pocas abstracciones. Pruebas realmente simples que se entrelazaron con las partes internas de la clase. Y una vez que tenga algunas miles de pequeñas pruebas en su lugar, seguramente no sentirá que se está moviendo más rápido cuando tenga que cambiar un centenar de ellas para refactorizar su código para usar el concepto de dominio X muy importante.
La luz se encendió para mí: TDD no es una habilidad de prueba. Es una habilidad de diseño. Solo puede llevarlo a un código bueno, simple y viable con práctica y un conocimiento constante de las instrucciones de diseño en las que lo lleva. Si está escribiendo pruebas por el bien de la cobertura del código, creará pruebas frágiles. Si está escribiendo pruebas para ayudarlo a diseñar sus abstracciones, entonces es solo una forma más rigurosa de escribir código de arriba hacia abajo. Primero puede ver el código desde la perspectiva de la persona que llama, lo que lo alienta a facilitarle la vida, en lugar de reflejar las partes internas de una clase en su borde exterior.
Creo que TDD es útil, pero no soy dogmático al respecto. Si esas "pruebas sin valor" dificultan el mantenimiento, ¡bórrelas! Trato las pruebas de la misma manera que el resto del código. Si se puede refactorizar y simplificar las cosas, ¡hazlo!
No lo he visto personalmente, pero he oído que algunos lugares rastrean la cobertura del código y los recuentos de pruebas. Entonces, si la recopilación de métricas es un efecto secundario de TDD, entonces podría ver eso también como negativo. Eliminaré con entusiasmo 1000 líneas de código, y si eso obsoleta 20 pruebas y cae el% de cobertura de mi código, bueno.
fuente
Voy a arriesgarme aquí y declarar con brutal honestidad que es literalmente una pérdida ritual de tiempo. (En la mayoría de las situaciones).
Compré un libro sobre Pruebas unitarias que también hablaba de TDD, y aunque estoy de acuerdo con los beneficios de UT, después de aproximadamente cien horas de probar TDD, renuncié a él por una infinidad de razones. Estoy haciendo publicaciones cruzadas aquí, pero TDD:
Otra preocupación es el grado de perfección debatido al que se debe hacer TDD para hacerlo con éxito. Algunos insisten en que si TDD no es realizado de manera persistente por todos en el equipo desde el comienzo del proyecto, solo sufrirá. Otros insisten en que nadie hace TDD por el libro. Si esto es cierto, se deduce que los practicantes de TDD están sufriendo, se den cuenta o no.
Por supuesto, si se argumenta que al hacer las cosas de una manera similar a TDD, obtendrá diseños que pueden funcionar fácilmente con TDD, bueno, hay formas mucho más rápidas de lograrlo, es decir, estudiando realmente los conceptos de componibilidad Hay muchos recursos por ahí, mucha teoría matemática rigurosa incluso (en gran parte en programación funcional pero también en otros campos). ¿Por qué no pasar todo su tiempo TDD aprendiendo ?
Culturalmente, TDD muestra síntomas de ser una práctica ritualista. Se basa en la culpa; fomenta el procedimiento sobre la comprensión; tiene toneladas de doctrinas y lemas ("fingir hasta que lo consigas" es realmente alarmante si lo miras objetivamente). La definición de Wikipedia de la palabra "ritual" es de hecho bastante apropiada:
fuente
Para agregar, otra preocupación con TDD que noté es:
¡TDD provoca un cambio inadvertido en el enfoque del equipo de desarrollo de Código de calidad a Casos de prueba y cobertura de código! ¡Personalmente no me gustó TDD ya que me hace menos creativo y hace que el desarrollo de software sea un proceso mecánico aburrido ! Los casos de prueba unitarios son útiles cuando se usan juiciosamente pero se convierten en una carga cuando se trata el objetivo del desarrollo de software.
Conozco a un tipo que es gerente y que técnicamente es aburrido una vez que se obsesionó con TDD. Fue algo tan mágico para él que creía que aportaría soluciones mágicas a todos los problemas en su software mal diseñado con un código menos mantenible. Sin decir lo que sucedió con ese proyecto, falló miserablemente en sus manos, mientras que todas sus cajas de prueba eran verdes. Supongo que TDD lo ayudó a obtener algún tipo de información estadística, como "99/100 de mis casos son verdes", etc., y esa fue la razón de su obsesión, ya que nunca podría evaluar la calidad o sugerir mejoras en el diseño.
fuente
Mi experiencia negativa principal es tratar de usar TDD para editar el código de otro programador que no tiene pruebas, o pruebas de integración muy, muy básicas. Cuando voy a agregar una función o corregir un problema con dicho código; Preferiría escribir una prueba primero (la forma TDD). Desafortunadamente, el código está estrechamente acoplado, y no puedo probar nada sin mucha refactorización.
La refactorización es un gran ejercicio de todos modos, pero se requiere para llevar el código a un estado comprobable. Y después de este paso, no tengo controles ni saldos para ver si mis cambios rompieron algo; antes de ejecutar la aplicación y examinar cada caso de uso.
Por otro lado, agregar funciones / corregir errores a un proyecto TDD se vuelve muy sencillo. Por naturaleza, el código escrito con TDD suele estar bastante desacoplado con pequeñas piezas para trabajar.
En cualquier caso, TDD es una guía. Sígalo hasta el punto en que encuentre que obtiene la máxima efectividad. Cobertura de prueba decente y código desacoplado, código bien escrito.
fuente
Hice la experiencia de que a veces confío demasiado en mis pruebas cuando se trata del diseño del sistema. Básicamente, soy demasiado bajo en los detalles de implementación esenciales para dar un paso atrás para ver el panorama general. Esto a menudo resulta en un diseño innecesariamente complejo. Lo sé, se supone que debo refactorizar el código, pero a veces tengo la impresión de que podría ahorrar mucho tiempo dando un paso atrás con más frecuencia.
Dicho esto, si tiene un marco como rieles donde sus decisiones arquitectónicas son muy limitadas, estos problemas son básicamente inexistentes.
Otro problema es cuando confía ciegamente en sus pruebas. La verdad es que, como cualquier otro código, sus pruebas también pueden tener errores. Sea tan crítico con sus pruebas como lo es con su implementación.
fuente
Como gran fanático de TDD, a veces veo estos inconvenientes
Costos de mantenimiento del código de prueba para pruebas similares, que varían solo levemente (creado a través de la duplicación de código (también conocido como copiar-pegar-herencia)). Si ya tiene uno, es fácil crear uno similar. Pero si no refactoriza el código de prueba, al eliminar la duplicación de código en métodos auxiliares, es posible que necesite algo de tiempo para corregir las pruebas si los detalles de implementación de su código comercial cambian.
Si está bajo presión de tiempo , puede verse tentado a eliminar las pruebas rotas (o comentarlas) en lugar de arreglarlas . De esta manera pierdes la inversión en las pruebas
fuente
Todavía tengo que encontrar más de un escenario como desarrollador de juegos donde valió la pena TDD. Y la instancia en la que se encontraba era un código que era de naturaleza puramente matemática y necesitaba un enfoque sólido para probar una gran cantidad de casos extremos simultáneamente, una necesidad poco frecuente.
Tal vez algo, algún día cambie de opinión, pero entre las prácticas de XP, la idea de refactorizar sin piedad y de que el código desarrolle su propia forma es mucho más importante y me lleva a la mayor productividad, cf. una cita de un artículo de James Newkirk :
Los conceptos de coraje y de apretar los circuitos de retroalimentación que menciona también son, en mi opinión, clave para la productividad.
fuente
¡Mi experiencia negativa de TDD, por limitada que sea, es simplemente saber por dónde empezar! Por ejemplo, intentaré hacer algo TDD y no tengo idea de dónde comenzar a prohibir probar cosas triviales (¿puedo renovar un
Foo
objeto, puedo pasar unQuux
aBaz
, y cosas por el estilo? Pruebas que no prueban nada ), o si estoy tratando de implementarlo en un proyecto existente, entonces encuentro que tendría que reescribir varias clases para poder usarlas en TDD. El resultado final es que abandono rápidamente la noción por completo.Probablemente no ayuda que a menudo soy la única persona en toda la empresa que sabe qué es la prueba de unidad (TDD o no) y por qué es algo bueno.
fuente
Foo
con objetos simulados en lugar deQuux
yBaz
directamente, luego puede llamar a la función que desea probar y luego verificar que los simulacros se llamaron con las funciones que espera. Los objetos simulados son la tecnología habilitadora que ayuda a desacoplar unidades y hacer que las unidades sean comprobables. Es por eso que los singletons son malvados, ya que a menudo no puedes simplemente burlarte de ellos. * 8 ')TDD fanáticos.
Para mí, son solo una de una larga lista de locos religiosos que llaman a mi puerta, tratando de demostrar que mi forma de hacer las cosas está irreparablemente rota y que el único camino hacia la salvación es Jesús, Kent Back o Unit Testing.
En mi opinión, su mayor mentira es que TDD te llevará a la
salvación deun mejor diseño de algoritmo. Vea el famoso solucionador Soduku escrito en TDD: aquí , aquí , aquí , aquí y aquíY compárelo. El solucionador de sudoku Peter Norvig no se hizo usando TDD, sino usando ingeniería antigua: http://norvig.com/sudoku.html
fuente
Si utiliza TDD de estos artículos "fanáticos", tendrá la sensación de seguridad errónea de que su software no tiene errores.
fuente
TDD tiene algunos beneficios:
TDD se trata de inversiones a largo plazo. El esfuerzo vale la pena cuando alcanza el modo de mantenimiento de su aplicación, y si la aplicación no está planificada para llegar a ese punto, es posible que nunca recupere la inversión.
Considero que el ciclo TDD rojo-verde con los pequeños pasos es similar a una lista de verificación para un avión. Es molesto y tedioso revisar todas y cada una de las cosas en el avión antes del despegue, especialmente si es trivialmente simple (los pequeños pasos del TDD) pero se ha descubierto que aumenta la seguridad. Además de verificar que todo funciona, esencialmente restablece el plano . En otras palabras, un avión se reinicia antes de cada despegue.
fuente
Mi experiencia negativa sobre TDD es algo que siento con muchas cosas nuevas e publicitadas. De hecho, disfruto de TDD porque garantiza la validez de mi código, y aún más importante: puedo reconocer las pruebas fallidas, después de agregar un nuevo código o cualquier tipo de refactorización.
Lo que me molesta acerca de TDD es el hecho de que hay muchas reglas o pautas al respecto. Como todavía es bastante nuevo, la mayoría de nosotros experimentamos ser principiantes en TDD. Entonces, lo que funciona bien para algunos de nosotros, podría no funcionar para otros. Lo que quiero decir es que no existe una forma real "incorrecta o correcta" de realizar TDD: existe la forma que funciona para mí y para mi equipo si tengo uno.
Por lo tanto, siempre que escriba pruebas, antes o después de que el código de producción realmente no importe, en mi humilde opinión, no estoy seguro de si las pruebas conducidas realmente significan que debe seguir todas las pautas que se indican en este momento, ya que aún no se ha demostrado que sean La solución ideal para el trabajo diario. Si encuentra una mejor manera de escribir pruebas, debe publicarla en un blog, discutirla aquí o escribir un artículo al respecto. Entonces, en diez años más o menos, podríamos haber compartido suficiente experiencia para poder determinar qué regla de TDD se puede suponer que es buena o no en una determinada situación.
fuente
Tengo, en más de una ocasión, un código escrito que descarté al día siguiente porque era torpe. Reinicié con TDD y la solución fue mejor. Por lo tanto, no he tenido demasiada experiencia negativa en TDD. Sin embargo, dicho esto, he pasado tiempo pensando en un problema y encontrando una mejor solución fuera del espacio TDD.
fuente
Descubrí que TDD funciona mal cuando se trata de sistemas emergentes. Soy un desarrollador de videojuegos, y recientemente usé TDD para crear un sistema que usa múltiples comportamientos simples para crear un movimiento de aspecto realista para una entidad.
Por ejemplo, hay comportamientos responsables de alejarlo de áreas peligrosas de diferentes tipos, y otros responsables de moverlo hacia áreas interesantes de diferentes tipos. Amalgamar la salida de cada comportamiento crea un movimiento final.
Las tripas del sistema se implementaron fácilmente, y TDD fue útil aquí para especificar de qué debe ser responsable cada subsistema.
Sin embargo, tuve problemas a la hora de especificar cómo interactúan los comportamientos y, lo que es más importante, cómo interactúan con el tiempo. A menudo no había una respuesta correcta, y aunque mis pruebas iniciales fueron aprobadas, el control de calidad podía seguir encontrando casos extremos en los que el sistema no funcionaba. Para encontrar la solución correcta, tuve que repetir varias conductas diferentes, y si actualizaba las pruebas cada vez para reflejar las nuevas conductas antes de comprobar que funcionaban en el juego, podría haber terminado tirando las pruebas una y otra vez. Así que eliminé esas pruebas.
Posiblemente debería haber tenido pruebas más fuertes que capturaron los casos extremos que QA descubrió, pero cuando tienes un sistema como este que se encuentra en la parte superior de muchos sistemas de juego y física, y estás lidiando con comportamientos con el tiempo, se vuelve un poco pesadilla para especificar exactamente lo que está sucediendo.
Es casi seguro que cometí errores en mi enfoque y, como dije para las entrañas del sistema, TDD funcionó de manera brillante e incluso admitió algunos refactores de optimización.
fuente