metodologia - ¿Cuáles son algunas de las razones por las cuales un único desarrollador debe usar TDD?
tdd pdf (20)
No voy a seguir ciegamente nada.
Esa es la actitud correcta. Yo uso TDD todo el tiempo, pero no me adhiero a él tan estrictamente como algunos.
El mejor argumento (en mi opinión) a favor de TDD es que obtienes un conjunto de pruebas que puedes ejecutar cuando finalmente llegas a las fases de refactorización y mantenimiento de tu proyecto. Si esta es su única razón para usar TDD, puede escribir las pruebas en cualquier momento que desee, en lugar de seguir ciegamente la metodología.
La otra razón por la que uso TDD es que escribir pruebas me hace pensar en mi API por adelantado. Me veo obligado a pensar en cómo voy a usar una clase antes de escribirla. Aspirar el proyecto en este alto nivel me funciona. Hay otras maneras de hacerlo, y si ha encontrado otros métodos (hay muchos) para hacer lo mismo, entonces le diría que siga haciendo lo que funcione para usted.
Soy un programador por contrato con mucha experiencia. Estoy acostumbrado a ser contratado por un cliente para ingresar y hacer un proyecto de software de una forma u otra por mi cuenta, generalmente de la nada. Eso significa una borrón y cuenta nueva, casi todo el tiempo. Puedo traer bibliotecas que he desarrollado para comenzar rápido, pero siempre son opcionales. (y depende de obtener las cláusulas IP adecuadas en el contrato) Muchas veces puedo especificar o incluso diseñar la plataforma de hardware ... así que estamos hablando de una libertad seria aquí.
Puedo ver los usos para construir pruebas automatizadas para cierto código: Bibliotecas con funcionalidad más que trivial, funcionalidad central con un alto número de referencias, etc. Básicamente, como el valor de una pieza de código sube a través del uso intensivo, puedo verlo Sería cada vez más valioso probar automáticamente ese código para que yo sepa que no lo rompo.
Sin embargo, en mi situación , me resulta difícil racionalizar nada más que eso. Adoptaré las cosas que resulten útiles, pero no voy a seguir ciegamente nada.
Encuentro que muchas de las cosas que hago en ''mantenimiento'' son en realidad pequeños cambios de diseño. En este caso, las pruebas no me habrían ahorrado nada y ahora tendrían que cambiar también. Un enfoque de diseño altamente repetitivo, de primer plano, funciona muy bien para mí. No puedo ver en realidad ahorrarme tanto tiempo con pruebas más extensas.
Los proyectos de pasatiempos son aún más difíciles de justificar ... por lo general son cualquier cosa, desde los fin de semana hasta un mes de duración. Los errores en el borde de los bordes rara vez importan, se trata de jugar con algo.
Leyendo preguntas como esta , La respuesta más votada parece decir que en la experiencia / opinión de ese afiche TDD en realidad pierde tiempo si tiene menos de 5 personas (incluso asumiendo un cierto nivel de competencia / experiencia con TDD). Sin embargo, eso parece estar cubriendo el tiempo de desarrollo inicial, no el mantenimiento. No está claro cómo se acumula TDD durante todo el ciclo de vida de un proyecto.
Creo que TDD podría ser un buen paso en el valioso objetivo de mejorar la calidad de los productos de nuestra industria en general. Sin embargo, el idealismo por sí solo ya no es tan efectivo para motivarme.
Creo que TDD sería un buen enfoque en equipos grandes, o cualquier equipo de tamaño que contenga al menos un programador poco confiable. Esa no es mi pregunta.
¿Por qué un único desarrollador con un buen historial adoptaría TDD?
Me encantaría saber de cualquier tipo de métrica realizada (formalmente o no) en TDD ... centrándose en desarrolladores individuales o equipos muy pequeños.
De lo contrario, las anécdotas de sus experiencias personales también serían agradables. :)
Por favor evite expresar opiniones sin experiencia para respaldarlo. No hagamos de esto una guerra de ideología. También se salta el argumento de mayor opción de empleo. Esto es simplemente una pregunta de eficiencia.
¿Su cliente posee el código fuente cuando entrega el producto? Si puede convencerlos de que entregar el producto con pruebas unitarias le agrega valor, entonces usted está vendiendo sus servicios y entregando un mejor producto. Desde la perspectiva del cliente, la cobertura de prueba no solo garantiza la calidad, sino que permite a los mantenedores futuros comprender el código mucho más fácilmente ya que las pruebas aíslan la funcionalidad de la interfaz de usuario.
Aquí hay algunos memes y mis respuestas:
"TDD me hizo pensar en cómo fallaría, lo que me convirtió en un mejor programador"
Con la experiencia suficiente, estar muy preocupado con los modos de falla, naturalmente, debe convertirse en parte de su proceso de todos modos.
"Las aplicaciones deben funcionar correctamente"
Esto supone que puedes probar absolutamente todo. En primer lugar, no vas a ser mejor para cubrir todas las pruebas posibles que para escribir correctamente el código funcional. "Las aplicaciones necesitan funcionar mejor " es un argumento mucho mejor. Estoy de acuerdo con eso, pero es idealista y no lo suficientemente tangible como para motivar tanto como me gustaría. Métricas / anécdotas serían geniales aquí.
"Funcionó muy bien para mi <componente de biblioteca X>"
Dije en la pregunta que vi valor en estos casos, pero gracias por la anécdota.
"Piensa en el próximo desarrollador"
Este es probablemente uno de los mejores argumentos para mí. Sin embargo, es bastante probable que el próximo desarrollador tampoco practique TDD, y sería un desperdicio o incluso una carga en ese caso. Evangelismo de puerta trasera es lo que equivale a eso. Sin embargo, estoy bastante seguro de que un desarrollador de TDD realmente lo atraería.
¿Cuánto va a apreciar los proyectos realizados en metodologías obligatorias en desuso cuando hereda uno? RUP, ¿alguien? Piense en lo que TDD significa para el próximo desarrollador si TDD no es tan bueno como todos piensan.
"Refactorizar es mucho más fácil"
Refactorizar es una habilidad como cualquier otra, y el desarrollo iterativo ciertamente requiere esta habilidad. Tiendo a tirar cantidades considerables de código si creo que el nuevo diseño ahorrará tiempo a largo plazo, y parece que también se descartarán muchas pruebas. ¿Cuál es más eficiente? No lo sé.
...
Probablemente recomendaría algún nivel de TDD a cualquier persona nueva ... pero todavía estoy teniendo problemas con los beneficios para cualquiera que haya estado en la cuadra varias veces. Probablemente comenzaré a agregar pruebas automatizadas a las bibliotecas. Es posible que después de hacer eso, vea más valor para hacerlo en general.
Creo que TDD como metodología no se trata solo de "tener pruebas al hacer cambios", por lo tanto, no depende del equipo ni del tamaño del proyecto. Se trata de observar las expectativas de uno sobre lo que hace un pice de código / una aplicación ANTES de comenzar a pensar realmente en CÓMO se implementa el comportamiento observado. El objetivo principal de TDD no es solo tener la prueba establecida para el código escrito, sino escribir menos código porque solo se hace lo que hace que la prueba sea verde (y se refactorice más adelante).
Si eres como yo y te resulta bastante difícil pensar en qué parte / toda la aplicación hace SIN pensar en cómo implementarla, creo que está bien escribir tu prueba después de tu código y así permitir que el código "maneje" el pruebas.
Si su pregunta no es tanto sobre test-first (TDD) o test-after (¿buena codificación?), Creo que las pruebas deberían ser una práctica estándar para cualquier desarrollador, ya sea solo o en un gran equipo, que crea código que permanece en producción más de tres meses. En mi experiencia, ese es el lapso de tiempo después del cual incluso el autor original tiene que pensar mucho sobre lo que estas veinte líneas de códigos complejos, súper optimizados pero escasamente documentados, realmente codifican. Si tienes pruebas (que cubren todas las rutas a través del código), hay menos para pensar, y menos para ERR, incluso años después ...
El desarrollador único debería usar TDD en su proyecto (el historial no importa), ya que eventualmente este proyecto podría pasar a otro desarrollador. O más desarrolladores podrían ser traídos.
Las personas nuevas tendrán extremadamente dificultades para trabajar con el código sin las pruebas. Romperán cosas.
El objetivo de escribir las pruebas primero es que impone los requisitos y las decisiones de diseño que está tomando. Cuando modifico el código, quiero asegurarme de que todavía se apliquen y de que sea bastante fácil "romper" algo sin obtener un compilador o un error en tiempo de ejecución.
Tengo un enfoque de prueba primero porque quiero tener un alto grado de confianza en mi código. De acuerdo, las pruebas deben ser buenas pruebas o no hacen cumplir nada.
Tengo algunas bases de código bastante grandes en las que trabajo y hay muchas cosas no triviales sucediendo. Es bastante fácil hacer cambios que se rompen y de repente sucede X cuando X nunca debería suceder. Mis pruebas me han salvado en varias ocasiones de cometer un error crítico (pero sutil) que podría haber pasado desapercibido para los evaluadores humanos.
Cuando las pruebas fallan, son oportunidades para mirarlas y el código de producción y asegurarse de que sea correcto. A veces, el diseño cambia y las pruebas deberán modificarse. Algunas veces escribiré algo que pase 99 de 100 pruebas. Esa 1 prueba que no pasó es como que un compañero de trabajo revise mi código (en cierto sentido) para asegurarse de que sigo construyendo lo que se supone que debo construir.
Las pruebas le permiten refactorizar con la confianza de que no está rompiendo el sistema. Escribir primero las pruebas permite que las pruebas definan el comportamiento de trabajo del sistema. Cualquier comportamiento que no esté definido por la prueba es, por definición, un subproducto y puede cambiar cuando se refactoriza. Las pruebas de escritura primero también conducen el diseño en buenas direcciones. Para respaldar la capacidad de prueba, descubres que debes desacoplar clases, usar interfaces y seguir un buen patrón (por ejemplo, Inversion of Control) para que tu código sea fácilmente comprobable. Si luego realiza pruebas, no puede estar seguro de haber cubierto todo el comportamiento esperado de su sistema en las pruebas. También descubres que algunas cosas son difíciles de probar debido al diseño, ya que es probable que se haya desarrollado sin tener en cuenta las pruebas, y te sientes tentado a escatimar u omitir las pruebas.
Generalmente trabajo solo y sobre todo hago TDD, los casos en los que no estoy simplemente donde no cumplo con mis prácticas o aún no he encontrado una buena manera de hacerlo TDD, por ejemplo con interfaces web .
Lo encuentro aún más útil cuando viajo solo. Con nadie a su alrededor para intercambiar ideas y nadie cerca para realizar revisiones por pares, necesitará cierta seguridad de que su código es sólido. TDD / BDD proporcionará esa seguridad para usted. TDD es un poco contraversial, sin embargo. Otros pueden estar completamente en desacuerdo con lo que estoy diciendo.
EDITAR: ¿Puedo agregar que si se hace bien, en realidad puede generar especificaciones para su software al mismo tiempo que escribe las pruebas. Este es un gran efecto secundario de BDD. Puedes hacerte ver como un súper desarrollador si estás sacando un código sólido junto con las especificaciones, todo por tu cuenta.
Mi mejor experiencia con TDD se centra en el proyecto pyftpdlib . La mayor parte del desarrollo es realizado por el autor original, y he hecho algunas pequeñas contribuciones, pero es esencialmente un proyecto en solitario. El conjunto de pruebas para el proyecto es muy minucioso y prueba todas las características principales de la biblioteca FTPd. Antes de registrar cambios o liberar una versión, se verifican todas las pruebas, y cuando se agrega una nueva característica, el banco de pruebas siempre se actualiza también.
Como resultado de este enfoque, este es el único proyecto en el que he trabajado que no tenía errores showtopper aparecen después de una nueva versión, tienen cambios revisados que rompieron una característica principal, etc. El código es muy sólido y yo Siempre me han impresionado los pocos informes de errores que se han abierto durante la vida del proyecto. Yo (y el autor original) atribuyo gran parte de este éxito al conjunto de pruebas integrales y la capacidad de probar cada ruta de código principal a voluntad.
Desde una perspectiva lógica, cualquier código que escriba debe ser probado, y sin TDD, entonces lo probará usted mismo manualmente. Por otro lado, pyftpdlib, el peor código por número de errores y la frecuencia de los principales problemas, es el código que los desarrolladores probaron / solo probaron y QA probó nuevas funciones de forma manual. Las cosas no se prueban debido a la crisis de tiempo o a las caídas. Las antiguas rutas de código se olvidan e incluso las características estables más antiguas terminan rompiéndose, las principales versiones terminan con características importantes no funcionales. etc. Las pruebas manuales son críticamente importantes para la verificación y algunas aleatorizaciones de las pruebas, pero de acuerdo con mis experiencias, diría que es esencial contar con pruebas manuales y un marco de pruebas de unidades cuidadosamente construido. Entre los dos enfoques, las brechas en la cobertura son menores, y la probabilidad de problemas solo se puede reducir.
No importa si eres el único desarrollador o no. Tienes que pensarlo desde el punto de vista de la aplicación. Todas las aplicaciones deben funcionar correctamente, todas las aplicaciones deben mantenerse, todas las aplicaciones deben ser menos problemáticas. Por supuesto, hay ciertos escenarios en los que un enfoque TDD podría no ser adecuado para usted. Esto es cuando la fecha límite se acerca muy rápido y no hay tiempo para realizar pruebas unitarias.
De todos modos, TDD no depende de un solo o un entorno de equipo. Depende de la aplicación como un todo.
No tengo una gran cantidad de experiencia, pero he tenido la experiencia de ver enfoques marcadamente contrastados para las pruebas.
En un trabajo, no hubo pruebas automatizadas. Las "pruebas" consistieron en hurgar en la aplicación, intentar lo que apareciera en su cabeza, para ver si se rompía. No hace falta decir que fue fácil para un código rotundo llegar a nuestro servidor de producción.
En mi trabajo actual, hay muchas pruebas automatizadas y un sistema CI completo. Ahora cuando se rompe el código, es inmediatamente obvio. No solo eso, sino que a medida que trabajo, las pruebas realmente documentan qué funciones están funcionando en mi código y qué no. Me da una gran confianza poder agregar nuevas funciones, sabiendo que si rompo las existentes, no pasarán desapercibidas.
Entonces, para mí, no depende tanto del tamaño del equipo, sino del tamaño de la aplicación. ¿Puedes hacer un seguimiento de cada parte de la aplicación? Cada requisito? ¿Cada prueba que necesita ejecutar para asegurarse de que la aplicación está funcionando? ¿Qué significa decir que la aplicación está "funcionando", si no tienes pruebas para probarlo?
Solo mi $ 0.02.
Siento que como desarrollador solista en un proyecto, especialmente uno más grande, tiendes a ser bastante delgado.
Está en medio de una gran refactorización cuando, de repente, se detectan algunos errores críticos que, por algún motivo, no aparecieron durante las pruebas previas a la publicación. En este caso, tiene que dejar todo y arreglarlos y después de haber pasado dos semanas arrancándose los pelos, finalmente puede volver a lo que estaba haciendo antes.
Una semana más tarde, uno de sus clientes más grandes se da cuenta de que absolutamente deben tener esta nueva y brillante característica, o de lo contrario no realizarán el pedido de esas unidades de 1M que ya deberían haber pedido hace un mes.
Ahora, tres meses después, ni siquiera recuerdas por qué empezaste a refaccionar en primer lugar, y mucho menos qué se suponía que debía hacer el código que estás refabricando. Gracias a Dios que hizo un buen trabajo al escribir esas pruebas unitarias porque al menos le dicen que su código refactorizado todavía está haciendo lo que se suponía que debía hacer.
Enjabona, enjuaga, repite.
..historia de mi vida durante los últimos 6 meses. : - /
TDD no se trata de probar se trata de escribir código. Como tal, proporciona muchos beneficios incluso a un solo desarrollador. Para muchos desarrolladores, es un cambio de mentalidad escribir un código más sólido. Por ejemplo, ¿con qué frecuencia piensas "ahora cómo puede fallar este código?" después de escribir el código sin TDD? Para muchos desarrolladores, la respuesta a esa pregunta es ninguna. Para los practicantes de TDD cambia el modo de pensar a hacer cosas como comprobar si los objetos o las cadenas son nulas antes de hacer algo con ellos porque estás escribiendo pruebas para hacer específicamente eso (romper el código).
Otra razón importante es el cambio. Cada vez que tratas con un cliente, parece que nunca pueden decidirse. Lo único constante es el cambio. TDD ayuda como una "red de seguridad" para encontrar todas las otras áreas que podrían romperse. Incluso en proyectos pequeños, esto puede evitar que pierdas un tiempo precioso en el depurador.
Podría seguir y seguir, pero creo que decir que TDD se trata más de escribir código que nada debería ser suficiente para justificar su uso como único desarrollador.
Tiendo a estar de acuerdo con la validez de su punto sobre los gastos generales de TDD para proyectos de "un desarrollador" o "pasatiempo" que no justifican los gastos.
Sin embargo, debe tener en cuenta que la mayoría de las mejores prácticas son relevantes y útiles si se aplican de manera consistente durante un largo período de tiempo.
Por ejemplo, TDD le está ahorrando tiempo de prueba / corrección de errores a largo plazo, no dentro de los 5 minutos posteriores a la creación de la primera prueba unitaria.
Eres un programador por contrato, lo que significa que abandonarás tu proyecto actual cuando esté terminado y cambiarás a otra cosa, muy probablemente en otra empresa. Su cliente actual deberá mantener y respaldar su aplicación. Si no dejas al equipo de soporte con un buen marco para trabajar, se quedarán estancados. TDD ayudará a que el proyecto sea sostenible. Aumentará la estabilidad del código base para que otras personas con menos experiencia no puedan hacer demasiado daño tratando de cambiarlo.
Lo mismo aplica para los proyectos de pasatiempos. Puede estar cansado de eso y querrá pasárselo a alguien. Puede ser exitoso comercialmente (piense en Craiglist) y tendrá 5 personas más trabajando además de usted.
La inversión en un proceso adecuado siempre vale la pena, incluso si se trata de una experiencia adquirida. Pero la mayoría de las veces te agradecerás que cuando comenzaste un nuevo proyecto decidiste hacerlo correctamente
Debes considerar OTRAS personas cuando haces algo. Usted tiene que pensar en el futuro, planificar el crecimiento , planificar la sostenibilidad .
Si no quieres hacer eso, mantente en la codificación cowboy, es mucho más simple de esta manera.
PS Lo mismo se aplica a otras prácticas:
- Si no comenta su código y tiene la memoria ideal, estará bien, pero alguien más que lea su código no lo hará.
- Si no documenta sus conversaciones con el cliente, alguien más no sabrá nada acerca de una decisión crucial que haya tomado
etc ad infinitum
Voy a responder esta pregunta bastante rápido, y espero que comiences a ver algunos de los razonamientos, incluso si sigues en desacuerdo. :)
Si tiene la suerte de estar en un proyecto de larga duración, habrá momentos en los que desee, por ejemplo, escribir su nivel de datos primero, luego tal vez el nivel de negocios, antes de avanzar en la pila. Si su cliente realiza un cambio de requisitos que requiere volver a trabajar en su capa de datos, un conjunto de pruebas de unidad en la capa de datos asegurará que sus métodos no fallen de forma indeseable (suponiendo que actualice las pruebas para reflejar los nuevos requisitos ) Sin embargo, es probable que también invoque el método de la capa de datos desde la capa empresarial, y posiblemente en varios lugares.
Supongamos que tienes 3 llamadas a un método en la capa empresarial, pero solo modificas 2. En el tercer método, es posible que aún recibas datos de tu capa de datos que parecen ser válidos, pero pueden romper algunas de las suposiciones que codificado meses antes. Las pruebas unitarias en este nivel (y más arriba) deberían haber sido diseñadas para detectar suposiciones rotas, y en su defecto deberían destacar que hay una sección de código que necesita ser revisada.
Espero que este ejemplo tan simplista sea suficiente para hacerte pensar en TDD un poco más, y que pueda crear una chispa que te haga pensar en usarlo. Por supuesto, si aún no ves el punto, y confías en tus propias capacidades para realizar un seguimiento de muchos miles de líneas de código, entonces no tengo ningún lugar para decirte que debes iniciar TDD.
Ya no refacciono nada sin un conjunto razonable de pruebas unitarias.
No hago TDD completo con pruebas unitarias primero y código segundo. Hago CALTAL - Code A Little, Test A Little - desarrollo. En general, el código va primero, pero no siempre.
Cuando me doy cuenta de que tengo que refactorizar, me aseguro de tener suficientes pruebas y luego me desvío de la estructura con la total confianza de que no tengo que mantener toda la arquitectura antigua se convierte en nueva arquitectura. plan en mi cabeza Solo tengo que hacer que las pruebas vuelvan a pasar.
Refactorizo los bits importantes. Obtenga el conjunto de pruebas existente para aprobar.
Entonces me doy cuenta de que olvidé algo, y estoy de nuevo en el desarrollo de CALTAL sobre las cosas nuevas.
Luego veo cosas que olvidé eliminar, pero ¿están realmente sin usar en todas partes? Eliminarlos y ver qué falla en la prueba.
Ayer mismo, en el medio de una gran refactorización, me di cuenta de que todavía no tenía el diseño correcto. Pero las pruebas aún tenían que pasar, así que tuve la libertad de refactorizar mi refactorización antes de que terminara la primera refactorización. (¡Vaya!) Y todo funcionó bien porque tuve un conjunto de pruebas para validar los cambios en contra.
Para volar solo, TDD es mi copiloto.
Ok mi turno ... Haría TDD incluso por mi cuenta (para código sin pico / experimental / prototipo) porque
- Piensa antes de saltar : me obliga a pensar en lo que quiero hacer antes de comenzar a generar el código. ¿Qué estoy tratando de lograr aquí ...? Si supongo que ya tenía esta pieza ... ¿cómo podría esperar que funcione? Alienta el diseño de objetos en la interfaz.
- Más fácil de cambiar : puedo hacer modificaciones con confianza .. ''No rompí nada en el paso 1 al 10 cuando cambié el paso 5''. Las pruebas de regresión son instantáneas
- Surgen mejores diseños : he encontrado mejores diseños emergentes sin que haya invertido esfuerzo en una actividad de diseño. test-first + Refactoring conducen a clases mínimamente acopladas, mínimas con métodos mínimos ... sin sobreingeniería ... sin código YAGNI. Las clases tienen mejores interfaces públicas, métodos pequeños y son más legibles. Esto es una especie de zen ... solo notas que lo tienes cuando lo "entiendes".
- El depurador ya no es mi muleta : sé lo que hace mi programa ... sin tener que pasar horas caminando por mi propio código. Hoy en día si paso más de 10 minutos con el depurador ... las alarmas mentales comienzan a sonar.
- Me ayuda a irme a casa a tiempo. He notado una marcada disminución en el número de errores en mi código desde TDD ... incluso si la afirmación es como una traza de consola y no una xUnit tipo AT.
- Productividad / Flujo : me ayuda a identificar el siguiente paso discreto que me llevará hacia el hecho ... mantiene la bola de nieve rodando. TDD me ayuda a entrar en ritmo (o lo que XPers llama flujo) más rápido. Obtengo una mayor cantidad de trabajo de calidad por unidad de tiempo que antes. El ciclo de refactorización rojo-verde se convierte en ... una especie de máquina de movimiento perpetuo.
- Puedo probar que mi código funciona con solo tocar un botón
- La práctica es perfecta. Me encuentro aprendiendo y divisando dragones más rápido ... con más tiempo de TDD bajo mi cinturón. Tal vez disonancia ... pero siento que TDD me ha convertido en un mejor programador incluso cuando no voy primero a la prueba. Descubrir oportunidades de refactorización se ha convertido en una segunda naturaleza ...
Voy a actualizar si pienso en más ... esto es lo que se me ocurrió en los últimos 2 minutos de reflexión.
TDD me permite definir más claramente el problema en mi cabeza. Eso me ayuda a concentrarme en implementar solo la funcionalidad que se requiere y nada más. También me ayuda a crear una mejor API, porque estoy escribiendo un "cliente" antes de escribir el código. También puedo refactorizar sin tener que preocuparme por romper nada.
También soy un programador de contrato. Aquí están mis 12 razones por las que me encantan las pruebas unitarias .
Interés propio motivado.
En mi caso, el único desarrollador se traduce a propietario de una pequeña empresa. He escrito una cantidad razonable de código de biblioteca para (aparentemente) hacer mi vida más fácil. Muchas de estas rutinas y clases no son ciencia espacial, así que puedo estar bastante seguro de que funcionan correctamente (al menos en la mayoría de los casos) revisando el código, algunas pruebas puntuales y depurando los métodos para asegurarse de que se comporten de la manera Creo que lo hacen Fuerza bruta, si quieres. La vida es buena.
Con el tiempo, esta biblioteca crece y se usa en más proyectos para diferentes clientes. Las pruebas consumen más tiempo. Especialmente casos en los que estoy (con suerte) corrigiendo errores y (aún más con suerte) no rompiendo otra cosa. Y esto no es solo por errores en mi código. Tengo que tener cuidado al agregar funcionalidad (los clientes siguen pidiendo más "cosas") o asegurarme de que el código aún funcione cuando se mueva a una nueva versión de mi compilador (Delphi!), Código de terceros, entorno de tiempo de ejecución o sistema operativo.
Llevado al extremo, podría pasar más tiempo revisando el código anterior que trabajando en proyectos nuevos (leer: facturables). Piense en ello como el ángulo de reposo del software (qué tan alto puede apilar el software no probado antes de que caiga :).
Técnicas como TDD me dan métodos y clases que están diseñados más cuidadosamente, más a fondo probado (antes de que el cliente los obtenga) y necesita menos mantenimiento en el futuro.
En definitiva, se traduce en menos tiempo haciendo mantenimiento y más tiempo para gastar haciendo cosas que son más rentables, más interesantes (casi cualquier cosa) y más importantes (como la familia).