¿El desarrollo impulsado por pruebas (TDD) realmente ha beneficiado un proyecto del mundo real?


36

No soy nuevo en la codificación. He estado codificando (en serio) durante más de 15 años. Siempre he tenido algunas pruebas para mi código. Sin embargo, en los últimos meses he estado aprendiendo diseño / desarrollo basado en pruebas (TDD) usando Ruby on Rails . Hasta ahora, no estoy viendo el beneficio.

Veo algunos beneficios al escribir pruebas para algunas cosas, pero muy pocas. Y aunque me gusta la idea de escribir la prueba primero, encuentro que paso mucho más tiempo tratando de depurar mis pruebas para que digan lo que realmente quiero decir que depurar el código real. Esto probablemente se deba a que el código de prueba a menudo es sustancialmente más complicado que el código que prueba. Espero que esto sea solo inexperiencia con las herramientas disponibles ( RSpec en este caso).

Sin embargo, debo decir que, en este punto, el nivel de frustración mezclado con la decepcionante falta de rendimiento es más que inaceptable. Hasta ahora, el único valor que veo de TDD es una creciente biblioteca de archivos RSpec que sirven como plantillas para otros proyectos / archivos. Lo cual no es mucho más útil, tal vez menos útil, que los archivos de código del proyecto real.

Al leer la literatura disponible, me doy cuenta de que TDD parece ser un tiempo masivo por adelantado, pero al final vale la pena. Me pregunto, ¿hay ejemplos del mundo real? ¿Esta frustración masiva alguna vez vale la pena en el mundo real?

Realmente espero no haberme perdido esta pregunta en otro lugar aquí. Busqué, pero todas las preguntas / respuestas tienen varios años en este momento. Fue una rara ocasión cuando encontré un desarrollador que diría algo malo sobre TDD, por lo que he pasado tanto tiempo en esto como lo he hecho. Sin embargo, noté que nadie parece señalar ejemplos específicos del mundo real. Leí una respuesta que decía que el tipo que depuró el código en 2011 le agradecería por tener un conjunto completo de pruebas unitarias (creo que ese comentario se hizo en 2008).

Entonces, me pregunto, después de todos estos años, ¿finalmente tenemos algún ejemplo que muestre que la recompensa es real? ¿Alguien realmente heredó o volvió al código que fue diseñado / desarrollado con TDD y tiene un conjunto completo de pruebas unitarias y realmente sintió una recompensa? ¿O descubriste que estabas pasando tanto tiempo tratando de descubrir qué estaba probando la prueba (y por qué era importante) que simplemente arrojaste todo el desastre y te metiste en el código?


1
Me ahorró más tiempo: porque somos muchas personas en el mismo proyecto, porque las actualizaciones de gemas pueden tener algunos efectos secundarios desconocidos, porque si todo es verde y tengo un error, sé dónde no vale la pena encontrar su raíz.
apneadiving


3
butunclebob.com/ArticleS.UncleBob.JustTenMinutesWithoutAtest Aquí hay una historia del tío Bob sobre una situación del mundo real que enfrentó.
Hakan Deryal

1
Al principio, pensé que las pruebas serían geniales para saber dónde no estaban los errores, pero rápidamente aprendí, como señaló @Hakan en el artículo del Tío Bob, generalmente surge porque te perdiste un caso de prueba. Lo que hace que esas pruebas sean bastante inútiles. De hecho, ese artículo señala que el desarrollo incremental es lo que funciona.
James

1
"Me parece que paso mucho más tiempo tratando de depurar mis pruebas para que digan lo que realmente quiero decir que depurar el código real" : pero ¿no es este precisamente el beneficio? Después, ¿todavía encuentra que pasa mucho tiempo depurando el "código real"? Los defensores de TDD argumentan que el tiempo dedicado a descubrir una manera de hacer que su código sea comprobable es en realidad un esfuerzo de diseño que beneficiará a su código.
Andres F.

Respuestas:


26

Este documento demuestra que TDD agrega un 15-35% de tiempo de desarrollo a cambio de una reducción del 40-90% en la densidad de defectos en proyectos similares.

El artículo hace referencia al documento completo (pdf) : Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat y Laurie Williams. “Realización de la mejora de la calidad a través del desarrollo basado en pruebas: resultados y experiencias de cuatro equipos industriales”. ESE 2008 .

AbstractoEl desarrollo impulsado por pruebas (TDD) es una práctica de desarrollo de software que se ha utilizado esporádicamente durante décadas. Con esta práctica, un ingeniero de software realiza un ciclo minuto a minuto entre escribir pruebas de unidad que fallan y escribir código de implementación para pasar esas pruebas. El desarrollo impulsado por pruebas ha resurgido recientemente como una práctica habilitadora crítica de metodologías ágiles de desarrollo de software. Sin embargo, poca evidencia empírica apoya o refuta la utilidad de esta práctica en un contexto industrial. Se realizaron estudios de caso con tres equipos de desarrollo en Microsoft y uno en IBM que adoptaron TDD. Los resultados de los estudios de caso indican que la densidad de defectos previos al lanzamiento de los cuatro productos disminuyó entre 40% y 90% en relación con proyectos similares que no utilizaron la práctica TDD. Subjetivamente,

El artículo completo también resume brevemente los estudios empíricos relevantes sobre TDD y sus resultados de alto nivel (sección 3 Trabajos relacionados ), incluidos George y Williams 2003, Müller y Hagner (2002), Erdogmus et al. (2005), Müller y Tichy (2001), Janzen y Seiedian (2006).


2
Según una discusión sobre Meta.StackOverflow , ¿podría agregar información adicional del documento que podría ser relevante para el autor de la pregunta y para las personas futuras que encuentren esta pregunta?
Thomas Owens

2
@ThomasOwens, pensé que la conclusión ("TDD agrega 15-35% de tiempo de desarrollo a cambio de una reducción de 40-90% en la densidad del defecto") fue la información adicional que responde a la pregunta original <_ <

44
Esta publicación se ha marcado por no contener suficiente información. Todavía no he leído el documento, pero parece que las personas quieren que se agregue más información al cuerpo de la respuesta. ¿Quizás discutir más sobre las condiciones específicas utilizadas en el estudio?
Thomas Owens

El 99% de todas las estadísticas son ficticias. : P Pero realmente se trata de contexto. ¿En qué tipo de equipo? ¿Una gran bandada de desarrolladores Java mediocres? Sí, creo que TDD los ayudaría con la productividad. Pero eso no significa que tener las habilidades arquitectónicas para diseñar y valorar el código robusto en primer lugar no los ayudaría aún más y, en mi opinión, TDD, que es la primera prueba, podría evitar que aprendan a hacerlo correctamente. Y sí, he oído que ayuda con el diseño. Hasta cierto punto, es probable que sea cierto, pero todavía es una falta de reconocimiento y una ayuda de banda para el problema raíz de la OMI.
Erik Reppen

Sería bueno si se agregaran algunos documentos más de la Biblioteca Digital de ACM o si se agregaran las palabras clave para usar en el motor de búsqueda. necesitamos más rigor en nuestras respuestas cuando hablamos de ágil y TDD
Rudolf Olah

16

Veo algunos beneficios al escribir pruebas para algunas cosas, pero muy pocas. Y aunque me gusta la idea de escribir la prueba primero, encuentro que paso mucho más tiempo tratando de depurar mis pruebas para que digan lo que realmente quiero decir que depurar el código real.

He estado trabajando TDD durante los últimos tres años, y mi experiencia es exactamente lo contrario. Paso menos tiempo escribiendo pruebas unitarias que habría depurado el código, si no hubiera escrito las pruebas unitarias.

No solo hago TDD, sino que trabajo de afuera hacia adentro, es decir, primero implemento el TDD de capa superior / gui. La implementación de la capa superior define los requisitos para la siguiente capa en el sistema, que desarrollo con TDD, etc. hasta que se haya implementado todo el código requerido para la función. A menudo, experimento que después de haber implementado una función como esta, y pruebo la función en el sistema real, funciona la primera vez. No todo el tiempo, pero a menudo.

Y dado que lleva más tiempo probar una función en el sistema de humo que ejecutar un par de pruebas unitarias, ahorro enormes cantidades de tiempo. En realidad, es más rápido para mí implementar una función usando TDD que no implementar la función sin escribir pruebas unitarias en absoluto.

Pero escribir pruebas unitarias es una habilidad que debe aprenderse y dominarse, como cualquier otra habilidad de programación. Cuando comencé a hacer TDD tenía 12 años de experiencia profesional en programación, y era un programador muy consumado. Pensé que escribir grandes conjuntos de pruebas para el código del sistema sería algo simple. Pero a medida que crecía la cantidad de código de prueba, y cambiaban diferentes partes del sistema, y ​​las pruebas existentes tenían que modificarse, aprendí que estructurar y escribir pruebas unitarias es en sí una habilidad que debe aprenderse y dominarse. Además, no todo el código es igualmente comprobable. El código del sistema tiene que estar muy poco acoplado para poder ser probado de manera eficiente. En realidad, aprender TDD me ha ayudado a hacer que el código del sistema esté más débilmente acoplado.

Pero mi eficiencia actual en el trabajo de TDD proviene de una combinación de dominar cómo escribir pruebas unitarias, pero también dominar la tecnología en la que se implementa el sistema (C # en este caso).

Hacer TDD mientras aprendo una nueva tecnología puede ser difícil, por ejemplo, aunque he estado haciendo un poco de programación de iPhone, no estoy escribiendo una cantidad significativa de pruebas unitarias, porque no domino el lenguaje, el objetivo c, ni domino la biblioteca. Por lo tanto, no tengo idea de cómo estructurar mis pruebas unitarias, y mucho menos cómo estructurar el código del sistema, cómo hacerlo comprobable.

Pero, ¿qué tan bien funciona en proyectos reales?

En el proyecto en el que he estado trabajando durante los últimos años, aunque existe el requisito de que el código esté suficientemente cubierto por las pruebas unitarias, soy el único en el equipo que escribe las pruebas primero. Pero el gran conjunto de pruebas me da confianza para poder refactorizar el sistema, y ​​tengo fe en que el sistema funcionará correctamente si se aprueba el conjunto de pruebas.

Pero desafortunadamente, debido a que muchas de las pruebas se escriben después del código del sistema, algunas de las pruebas en sí mismas son defectuosas, es decir, realmente no prueban lo que estaban destinadas a probar. Esto no se puede evitar. Cada vez que escribe un fragmento de código, hay una probabilidad de que el código no funcione según lo previsto, es decir, hay un error. Lo mismo vale para el código de prueba. Por lo tanto, existe la probabilidad de que escriba una prueba que pase aunque el código que debería probar no funciona como se esperaba.

Escribir la prueba primero, verificando no solo que obtiene una falla de prueba, sino que la prueba falla con exactamente el mensaje de error que espera antes de implementar el código del sistema, lo que reduce seriamente el riesgo de un error en el código de prueba de la unidad.

Para resumir, en mi experiencia, una vez que haya dominado el arte de TDD, no solo ahorrará tiempo a largo plazo, sino que ahorrará tiempo por adelantado. Pero lleva tiempo, incluso para un programador experimentado, dominar el arte de TDD. Y se necesita aún más tiempo para que un equipo de desarrolladores de diferentes habilidades domine el arte de TDD.


9

Nos hemos beneficiado masivamente.

Somos un comerciante de nivel 1, lo que significa que procesamos más de seis millones de transacciones de pago por año.

Nuestro sistema de pasarela de pago tiene miles de pruebas unitarias y de integración. Estas pruebas nos dan confianza en nuestra capacidad para procesar pagos. Quiere estar seguro de que los frenos de su automóvil funcionan, ¿no es así? Queremos estar seguros de que no perderemos nuestro negocio porque no podemos procesar los pagos.

La cobertura del código le brinda esa confianza. Por supuesto, no es suficiente por sí solo, pero es un muy buen comienzo.

La mayor parte de nuestro sistema de pasarela de pago fue escrito usando TDD. Algunos aspectos eran bastante difíciles de probar, por lo que hemos decidido cortar esquinas sacrificando algo de cobertura de código. Volveremos y abordaremos estos problemas eventualmente.

Personalmente, me resulta difícil escribir cualquier lógica antes de escribir pruebas. Dicho esto, me tomó un poco de tiempo comenzar a pensar en forma TDD.

Referencia de Visa PCI: http://usa.visa.com/merchants/risk_management/cisp_merchants.html


3
"Volveremos y abordaremos estos problemas eventualmente". - Probablemente no ... no, a menos que te den una bofetada con un error horrible. Estas áreas se convertirán en la columna vertebral de todo lo demás y guiarán todo el diseño hacia adelante porque nadie querrá invertir los recursos para rehacerlos y nadie querrá forzar ningún cambio que pueda hacer algo malo. Sucede cada vez: P
Edward Strange

Estás adivinando cuando te digo lo que está sucediendo dentro de la empresa. Cuando nos comprometemos, podemos comprometer código con una cobertura de código del 70%. Esto aumenta constantemente por el plomo de CI. En unos meses, el umbral mínimo de cobertura del código aumentará en un pequeño porcentaje. Después de eso no habrá más remedio que introducir más pruebas.
CodeART

7

Aunque las pruebas a menudo se consideran simplemente una forma de hacer demasiado por algunas personas, creo que realmente vale la pena en ciertos casos.

He desarrollado un solucionador de sudoku asesino para la escuela durante aproximadamente 3 meses, utiliza muchas "estrategias" para eliminar posibilidades y soluciones. El hecho es que, un error en una posibilidad puede ser fatal y resultar en un problema para resolver el sudoku porque cuando se elimina alguna posibilidad, ya no lo intentas, y si fue la solución, el programa no puede resolver la cuadrícula más.

Pero es realmente difícil de probar manualmente, es decir, hay una grilla, puedo ver qué estrategias están haciendo qué en un ejemplo del mundo real, pero no puedo verificar todo el tiempo cada vez que se aplica una estrategia porque esto representa demasiados datos.

Y las estrategias aplicadas en una determinada cuadrícula son bastante "aleatorias", es decir que no usará todas en una cuadrícula en particular.

Así que escribí pruebas en cada estrategia, verificando el resultado en cada celda, usando situaciones simples (por ejemplo, solo dos celdas ya han eliminado las posibilidades) y me ahorró horas al día cuando desafortunadamente tenía una grilla que no podía resolverse. Porque ya sabía dónde estaba el problema.


2
Siento que esta pregunta está empujando más en la prueba primero, implementa más tarde la estrategia. Por supuesto, las pruebas son útiles para depurar aplicaciones en las que sería tedioso probar cada posibilidad usted mismo.
Alex Hope O'Connor

6

La ventaja de TDD es que descubres cómo llamar a tu código antes de escribir el código real.

En otras palabras, TDD ayuda a diseñar su API.

En mi experiencia, esto da como resultado mejores API, lo que a su vez proporciona un mejor código.


EDITAR: Como escribí, esto fue "en mi experiencia", es decir, al escribir "proyectos del mundo real", pero desafortunadamente esto es con una base de código fuente cerrada que no puedo dejar que el mundo vea. De los comentarios puedo entender que esto es lo que realmente se solicita, y no solo una confirmación de la mera existencia de tales proyectos.

También descubrí, nuevamente en mi experiencia personal, que el beneficio real se muestra cuando ingresa al modo de mantenimiento porque los requisitos tienden a cambiar. Las API más limpias hicieron que fuera mucho más fácil expresar los requisitos nuevos o modificados en el código de prueba, y todas las pruebas hacen que sea muy fácil ver para un futuro mantenedor cómo se llamará el código y qué se puede esperar.

Los casos de prueba están ejecutando versiones de la especificación y le permite ver muy, muy fácilmente cómo invocar su API. Esta es quizás la forma más útil de la documentación "CÓMO" que he visto hasta ahora (compárese con la documentación "POR QUÉ" como JavaDoc) ya que está seguro de que es correcta (de lo contrario, la prueba fallaría).

Últimamente, he tenido que mantener un cliente ftp programable con un conjunto muy grande de opciones que influyen en la forma en que funciona la aplicación. TDD se ha introducido recientemente para una nueva funcionalidad y el gran conjunto de pruebas nos permite hacer revisiones al tiempo que confiamos en que la funcionalidad utilizada todavía funciona como se esperaba. En otras palabras, esta transición resultó ser muy rápida.


8
Esta respuesta parece estar completamente al lado de la pregunta, ya que la pregunta requiere ejemplos del mundo real . Pero como tres personas pensaron que "esta respuesta es útil", me falta algo.

3
De acuerdo, pero me falta la reputación de rechazar el voto. Esto es solo el "TDD da mejores resultados" sin ningún ejemplo de un proyecto derivado de TDD en mantenimiento para respaldar la respuesta que quería evitar.
James

Ahora que varias personas estuvieron de acuerdo conmigo, me atrevo a votar. ¿Algún votante, o el autor, podría dar un paso adelante y decirnos por qué esta es una buena respuesta?

@delnan "Me atrevo a votar": una interesante elección de palabras. ¿La edición cayó en su gusto?

Sí, eliminé mi voto negativo ahora que lo noté.

5

La importancia de un enfoque particular para las pruebas depende de cuán crítico sea el sistema en desarrollo y cuánto depende de él otro sistema crítico. Un script de libro de visitas simple para su sitio web difícilmente podría considerarse crítico para la misión, pero si el sitio web en el que se ejecuta podría verse comprometido por un error que permitió la entrada sin filtrar a la base de datos y ese sitio ofrece un servicio vital, de repente se vuelve mucho más importante para que el script del libro de visitas se pruebe a fondo. Lo mismo también es cierto para el marco / código de biblioteca. Si desarrolla un marco con un error, entonces todas las aplicaciones que usan esa función también tienen el mismo error.

El desarrollo impulsado por pruebas le brinda una capa adicional de seguridad cuando se trata de pruebas. Si escribe las pruebas junto o incluso después del código que desea probar, entonces existe un riesgo real de que se equivoquen las pruebas. Si primero escribe todas las pruebas, entonces la forma en que el código funciona internamente no puede influir para lo que escribe las pruebas y, por lo tanto, hay menos posibilidad de que escriba pruebas inadvertidamente que piensan que un resultado erróneo en particular es correcto.

El desarrollo impulsado por pruebas también alienta a sus desarrolladores a escribir código que sea fácil de probar, ¡porque no quieren tener aún más trabajo por hacer! El código que es fácil de probar tiende a ser un código fácil de entender, reutilizar y mantener.

Y el mantenimiento es donde realmente cosecharás las recompensas de TDD. La gran mayoría del esfuerzo de programación dedicado al software está relacionado con el mantenimiento. Esto significa hacer cambios en el código en vivo para darle nuevas características, corregir errores o adaptarlo a nuevas situaciones. Al realizar dichos cambios, debe asegurarse de que los cambios que realice tengan el efecto deseado y, lo que es más importante, que no tengan efectos inesperados. Si tiene un conjunto de pruebas completo para su código, entonces es fácil verificar que cualquier cambio que realice no esté rompiendo otra cosa, y si los cambios que realiza rompen otra cosa, puede localizar rápidamente la razón. Los beneficios son a largo plazo.

Dijiste lo siguiente en tu pregunta:

Veo algunos beneficios al escribir pruebas para algunas cosas, pero muy pocas. Y aunque me gusta la idea de escribir la prueba primero, encuentro que paso mucho más tiempo tratando de depurar mis pruebas para que digan lo que realmente quiero decir que depurar el código real. Esto probablemente se deba a que el código de prueba a menudo es sustancialmente más complicado que el código que prueba. Espero que esto sea solo inexperiencia con las herramientas disponibles (rspec en este caso).

Esto parece sugerirme que no estás haciendo pruebas. Se supone que una prueba unitaria es extremadamente simple, solo una secuencia de llamadas a métodos, seguida de una afirmación para comparar el resultado esperado con el resultado real. Se supone que son simples porque los errores en sus pruebas serían desastrosos, y si introduce bucles, ramificaciones u otro control de lanzamiento de programas en la prueba, es más probable que la prueba tenga un error introducido. Si pasa mucho tiempo depurando pruebas, esto indica que sus pruebas son demasiado complicadas y debe simplificarlas.

Si las pruebas no se pueden simplificar, solo ese hecho sugiere que hay algo mal con el código que se está probando. Por ejemplo, si su clase tiene métodos largos, métodos con muchas declaraciones if / elseif / else o switch o una gran cantidad de métodos que tienen interacciones complejas dictadas por el estado actual de la clase, entonces las pruebas necesariamente tendrán que ser extremadamente complejas para proporcionar cobertura de código completo y probar todas las eventualidades. Si su clase tiene dependencias codificadas de otras clases, esto nuevamente aumentará el número de aros a los que tendrá que saltar para probar su código de manera efectiva.

Si mantiene sus clases pequeñas y altamente enfocadas, con métodos cortos con pocas rutas de ejecución e intenta eliminar el estado interno, entonces las pruebas se pueden simplificar. Y este es el quid de la cuestión. Un buen código es inherentemente fácil de probar. Si el código no es fácil de probar, entonces probablemente haya algo mal con él.

Escribir pruebas unitarias es algo que lo beneficia a largo plazo, y evitarlas es simplemente acumular problemas para más adelante. Es posible que no esté familiarizado con el concepto de deuda técnica, pero funciona de manera muy similar a la deuda financiera. No escribir pruebas, no comentar código, escribir en dependencias codificadas, etc., son formas de endeudarse. Usted "toma prestado" el tiempo cortando esquinas desde el principio y esto podría ayudarlo a alcanzar un plazo ajustado, pero el tiempo que ahorra al principio del proyecto es en préstamo. Cada día que pasa sin limpiar el código, comentarlo correctamente o crear un conjunto de pruebas le costará interés. Cuanto más se prolonga, más interés se acumula. Eventualmente, descubrirá que su código se ha convertido en un enredo en el que no puede hacer cambios sin desencadenar consecuencias no deseadas.

Se podría pensar en escribir pruebas unitarias temprano y mantenerlas actualizadas como una forma de "crédito técnico". Estás dedicando tiempo al banco al gastarlo al principio del proyecto en seguir las buenas prácticas. Ganará interés en esta previsión más adelante cuando llegue a la fase de mantenimiento del proyecto. Cuando desee realizar un cambio, puede validar fácilmente la corrección del cambio y que no tiene efectos secundarios no deseados, y puede obtener actualizaciones rápidamente y sin problemas. Si aparecen errores, puede agregar una nueva prueba de unidad que ejercite el error, luego corrija el error en el código. La próxima vez que ejecute la prueba de la unidad, podrá verificar que se solucionó el error y que no causó ningún otro problema. Además, evitará "regresiones",

TL: DR - Sí, son una ayuda del mundo real, pero son una inversión. Los beneficios solo se hacen evidentes más tarde.


1
Compré esta lógica hace meses. Me encanta la idea detrás de TDD, solo encuentro la realidad un poco desconcertante. Además, noto que incluso aquí, no hay ejemplos reales en los que la herencia de un proyecto basado en TDD haya valido la pena. ¿Has vuelto a una antigua base de código que tenía un montón de pruebas unitarias y valió la pena?
James

Lamentablemente no, porque nadie más parece construir pruebas unitarias, al menos no en ninguno de los códigos que heredé de desarrolladores anteriores. Mi vida hubiera sido mucho más fácil si lo hubieran hecho. Le sugiero que consulte el libro en el enlace, que tiene ejemplos del mundo real, aunque es para PHP en lugar de Rails. amazon.com/…
GordonM

Soy un gran crítico del uso general, pero no culparía a nadie por usar este enfoque en un sistema financiero incrustado o crítico.
Erik Reppen

4

Estoy usando TDD con bastante frecuencia en el trabajo. Mi experiencia es que TDD se justifica porque no paga tiempo o esfuerzo adicional, lo ahorra .

  • Como uso TDD, paso mucho menos tiempo depurando o algo así. Simplemente funciona desde el principio porque no considero que el código productivo esté escrito mientras las pruebas no pasen.

  • El control de calidad informa mucho menos errores, por lo que ahorramos costos en la reparación de nuestro código después de un lanzamiento. Esto se debe a que TDD no le permite escribir código sin una prueba, por lo que la cobertura del código es mucho mejor.

  • Puedo ejecutar mi código (productivo) con mucha más frecuencia y rapidez porque no necesito iniciar todo el servidor de aplicaciones. Comenzar la prueba unitaria es un orden de magnitud más rápido. Por supuesto, solo me beneficio cuando la prueba ya es ejecutable cuando quiero probar el código productivo. Cuando las pruebas llegan después, se pierde este beneficio.

  • Hago mucho menos pruebas manuales. Mis colegas que no practican TDD pasan mucho tiempo haciendo clic en la aplicación hasta que llegan al punto donde se ejecuta el nuevo código. Solo pruebo manualmente una vez, justo antes de comprometerme con el control de versiones.

  • Incluso si uso un depurador, es mucho más rápido depurar la ejecución de una prueba que de toda la aplicación.

Tal vez piense en las pruebas unitarias como pruebas de regresión. Ese es uno de sus propósitos, pero entenderlos como una herramienta para el desarrollo los hace mucho más valiosos.


¡La calidad es gratis!
MathAttack

2
¡La mala calidad es cara!
Wolfgang

3

Otra ventaja (además de las mencionadas por las otras personas que han respondido) entra en juego cuando los evaluadores de aceptación del cliente o (Dios no lo quiera) los usuarios de producción descubren un error. Convierta el informe de error en una prueba de estilo TDD para la clase que parece tener la culpa. Míralo fallar. Arreglalo. Míralo pasar. Entonces sabes que has solucionado el error. Esta técnica me ha ahorrado horas.


2

Bueno, sé que personalmente me beneficio al ser el doble de rápido que mis compañeros desarrolladores y escribir menos de la mitad de los errores que hacen porque NO hacen TDD. Gente que probablemente debería ser mejor que yo ... Los supero en al menos un factor de 2.

No llegué allí de inmediato. Soy bastante bueno escribiendo código del brazalete y sin arnés. Parecía un gran desperdicio escribir toda esta basura extra. Pero hace varias cosas, incluidas (no exclusivas):

  • Forzar un diseño orientado al desacoplamiento y la reutilización (todo debe reutilizarse en una prueba unitaria).
  • Proporcionar una plataforma para desarrollar código en pequeños fragmentos y módulos para que no tenga que resolver todo y terminarlo antes de ejecutar un simple tipo de prueba "¿Incluso compila y toma datos?".
  • Proporcionar una plataforma de prueba rápida para realizar cambios cuando las personas demandan cambios de características que no esperaba.

Un ejemplo de este bit posterior es un proyecto en el que estoy trabajando actualmente en el que el líder de repente decidió reescribir TOTALMENTE el protocolo de comunicación que usó por casi 0 razones. Pude responder a ese cambio en 2 horas, ya que lo había desacoplado de todo lo demás y pude trabajar en él de manera completamente independiente hasta que el último lo vinculó e intente el paso de prueba. La mayoría de mis compañeros de trabajo probablemente habrían estado en eso por un día o más porque su código no estaría desacoplado y estarían cambiando aquí, allá, en todas partes ... compilando todo ... pruebas de integración ... repetir, repetir ... Lleva mucho más tiempo de esa manera y no es tan estable.


2

La respuesta es sí. En mi empresa llevamos más de 20 años desarrollando una aplicación C ++. El año pasado, ingresamos a TDD en algunos módulos nuevos, y las tasas de defectos disminuyeron significativamente. Nos gustó tanto que algunos de nosotros incluso agregamos pruebas al código heredado cada vez que cambiamos algo allí.

Además, se completó un módulo completo de principio a fin, pasando por la producción, sin demostrar un error (y también es un módulo crítico). Su desarrollo, por lo tanto, fue más rápido de lo habitual, porque lo que sucedería de otro modo es que un módulo se "completaría", solo para regresar 4-5 veces de la prueba beta para la corrección de errores. Fue una mejora sustancial, y los desarrolladores también estaban más satisfechos con el nuevo proceso.

No he hecho mucho Rails TDD, pero he hecho mucho en C ++, C #, Java y Python. Puedo decirte que definitivamente funciona. Supongo que pasas mucho tiempo pensando en los nombres de los exámenes porque no tienes la suficiente confianza. Escriba su prueba primero, pero deje fluir su creatividad ...

Me di cuenta de que una vez que realmente dominas TDD, empiezas a preocuparte un poco menos en "¿Cómo voy a nombrar esta prueba ... argh!", Y simplemente fluyes con ella, refactorizando y adaptando lo que ya está escrito pruebas para adaptarse a la situación actual.

Hora de una propina

Consejo # 1

Entonces, el consejo que creo que debería ayudarte es no preocuparte tanto. Una de las cosas más bonitas sobre TDD es que te da coraje para cambiar cosas que ya están escritas y funcionando. Y eso incluye las pruebas.

Consejo # 2

Comience nuevas pruebas de clase con una simple prueba "canCreate", solo para establecer su mente en la dirección correcta, como en "Ok, estoy trabajando en esta clase ahora ... correcto".

Luego comience a agregar más pruebas, pero solo una a la vez, y asegúrese de que cada prueba que cree sea el siguiente caso más simple que se le ocurra en ese momento (piense en ello durante no más de 30 segundos y luego agote el tiempo de espera). con lo mejor que tienes en ese punto).

Y recuerda

No se preocupe por refactorizar las pruebas existentes o incluso eliminar las obsoletas o redundantes. No muchas personas se dan cuenta de esto, pero en TDD realmente obtienes 2 redes de seguridad por el precio de 1. Tus pruebas son una red de seguridad para los cambios en el código de producción, pero tu código de producción también es una red de seguridad para refactorizar las pruebas. La relación es mutua. En realidad es un buen caso de acoplamiento apretado.

Dale otra oportunidad. Y permítanme recomendarles ver Clean Code Casts , especialmente aquellos sobre TDD.


1

Ejemplo no trivial del mundo real:

Tuve que escribir una función de transformación de estructura de datos. La entrada sería una estructura de datos (en realidad, una estructura de datos anidada, muy similar a un árbol) y la salida sería una estructura de datos similar. No pude visualizar la transformación real en mi mente. Uno de los principales beneficios de TDD (para mí, de todos modos) es la aplicación de pequeños pasos si no sabes cómo proceder (ver Kent Becks "TDD por ejemplo"). Como no sabía a dónde iba esto, comencé con los casos básicos simples, como entradas vacías o triviales, y avancé hasta casos más complicados hasta que supuse que los tenía todos cubiertos. Al final tuve un algoritmo de trabajo y las pruebas que lo probaron. Las pruebas no solo prueban que mi implementación está funcionando en este momento, sino que también me impiden arruinar cualquier cosa más adelante.


-1

No me gusta la idea de seguir ciegamente ningún consejo genérico porque no creo que haya una sugerencia única que ayude a la mayoría de los desarrolladores a ser más productivos y reducir defectos en las aplicaciones. Según mi experiencia, cuanto más te preocupes por la calidad, más perderás en la cantidad de nuevas funciones entregadas. Por lo tanto, el nivel de importancia que desea otorgar a la calidad frente a la capacidad de entrega dependerá realmente de su producto y su estrategia actual, y lo más probable es que alguien más decida estratégicamente qué es más importante por el momento: robustez o capacidad de entrega.

Incluso esta decisión no es negra o blanca. Probablemente algunas partes de su aplicación deben ser robustas, mientras que otras no tienen que serlo. Una vez que identifique qué partes deben tener un alto grado de calidad, debe enfocarse en ellas desde la perspectiva de la prueba, ya que desea garantizar una alta calidad a esas partes.

Todo lo que he dicho hasta ahora no tiene nada que ver con TDD específicamente en el sentido de escribir pruebas antes de la implementación, pero creo que es importante separar los beneficios de haber probado el código en lugar de escribir las pruebas primero.

Una vez que comprenda los beneficios de la prueba en sí, TDD o no, puede discutir la estrategia de prueba para el código que desea que esté cubierto por las pruebas. Algunas personas argumentarán que si escribe las pruebas más tarde, perderá algunas condiciones en sus pruebas, pero creo que debería ser usted quien evalúe si eso se aplica a usted. Ciertamente no se aplica a mí.

Entonces, así es como funciona para mí. Básicamente, hay dos situaciones que me harán escribir pruebas: mejorará la calidad solamente o también acelerará el desarrollo de algunas funciones. Entonces, una situación en la que escribiré pruebas es cuando no hay nuevas características en la cartera de pedidos y luego puedo decidir mejorar el rendimiento de la aplicación, simplificar la base de código o mejorar el conjunto de pruebas. Otra situación es la necesidad de tener un código de trabajo sólido donde los errores tengan un impacto lo suficientemente grande en los clientes reales. Otro más es para probar código complejo que es fácil de romper cuando se trabaja en él. Como ejemplo, hay una clase QueryBuilder en mi base de código que se encarga de muchos casos de uso y sería fácil romper algunos de ellos al corregir un error o agregar una nueva característica.

Finalmente, existe el caso en el que escribir las pruebas primero me permite escribir una función más rápido que no escribir las pruebas en absoluto. QueryBuilder también fue un caso en el que esta regla también se aplicó, pero no significa que TDD también sea el mejor camino. Otro ejemplo de TDD que ayuda en la velocidad de desarrollo es para probar la generación de Excel, por ejemplo, mientras que en la aplicación real puede que tenga que realizar varios pasos cada vez que quiera probar alguna condición específica en la generación. O si necesita crear algunos registros para probar una función y es difícil o imposible eliminarlos manualmente después de haber probado el código manualmente.

Entonces, si le resulta más fácil reproducir los pasos para ejecutar algún código en desarrollo mediante programación (a través de pruebas), hágalo. Pero si escribir la prueba es más complicado que probarlo manualmente, debe decidir si es el momento de centrarse en la calidad o si tiene muchas solicitudes en su cartera de pedidos y alguien en la empresa probablemente lo sabrá mejor y le permitirá sepa dónde debe centrarse de acuerdo con sus necesidades actuales y la estrategia de la empresa.

En un mundo ideal, todo el código se prueba, pero no se puede pretender que no hay una compensación y asumir que TDD es siempre el mejor y único camino. Al igual que con todas las mejores prácticas, siempre debe centrarse en lo que es mejor para la empresa para la que trabaja en lugar de lo que es mejor para usted. Una vez que trabaje por cuenta propia, es libre de decidir realizar TDD todo el tiempo si cree que es el mejor camino. Si su empresa cree que todo el código debe ser probado, entonces debe escribir pruebas para todo el código que escriba. Pero para la mayoría de los casos, debe tener una idea general y comprender las compensaciones antes de tomar cualquier decisión. Lo sentimos, pero esta no es una ciencia exacta y no hay una respuesta fácil (o difícil) de talla única que deba seguir siempre.

Igual que con los patrones de diseño. Comprenda cómo funcionan y por qué han sido creados y qué tipo de problemas resuelven y cuáles son sus inconvenientes también. Comprender el razonamiento es mucho más importante que recordar las soluciones propuestas. Lo que hoy es una operación costosa puede lograrse fácilmente mañana con otras tecnologías. Si la premisa para alguna solución bien establecida ya no es válida, lo más probable es que la solución ya no sea la mejor para usar. Cuando los requisitos, la tecnología disponible o la estrategia de la empresa han cambiado, siempre debe reevaluar su caja de herramientas y, cuando eso suceda, debe comprender por qué eligió cada ruta en primer lugar en lugar de tomarlas como las mejores opciones.


esto ni siquiera intenta responder a la pregunta: "¿finalmente tenemos algún ejemplo que muestre que la recompensa es real? ¿Alguien ha heredado o vuelto al código que fue diseñado / desarrollado con TDD y tiene un conjunto completo de pruebas unitarias y en realidad sintió una recompensa? "
mosquito

1
Responde, pero como no compartes mi opinión, le das -1 :) Básicamente, cualquiera que no intente mostrar los valores de TDD dará una respuesta no deseada desde tu punto de vista;) Déjame adivinar . Eres un evangelizador de TDD, ¿verdad? :) Por cierto, la verdadera pregunta del autor es si TDD vale la pena o no. No tienes que practicar TDD para responder eso. ¿Fortran vale la pena por escribir aplicaciones web? ¿Has probado antes de contestar?
rosenfeld

No tengo una opinión sobre TDD, y no uso los votos como me gusta / no me gusta (es un sitio de preguntas y respuestas, no un Facebook). Según mi lectura, esta "respuesta" simplemente no aborda la pregunta formulada, ni positiva ni negativamente
mosquito

Desde mi punto de vista, esta no es una pregunta técnica, como "¿cómo hago X con nginx?". Hay respuestas correctas para preguntas como esa, pero no para preguntas cualitativas y subjetivas como esta, cuando el autor realmente quiere saber las opiniones de otros sobre TDD y si vale la pena. Ese fue mi intento de mostrar mi punto de vista. No tengo idea de cómo una respuesta podría ser la correcta, ya que todas me parecen opiniones personales. No puede medir efectivamente si TDD vale o no. Cualquier artículo que intente hacer eso es fundamentalmente incorrecto.
rosenfeld

"Este sitio es todo un recorrido obteniendo respuestas . No es un foro de discusión ..."
mosquito
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.