La gente dice que "hablar sobre TDD apenas funciona, si quieres convencer a alguien de TDD, muéstrale los resultados". Sin embargo, ya estoy obteniendo excelentes resultados sin TDD. Mostrándome que las personas que usan TDD obtienen buenos resultados no serán convincentes, quiero ver que las personas que escriben tanto TDD como no TDD obtengan mejores resultados con TDD.
A pesar de todo esto, estoy interesado en probar TDD. Sin embargo, no estoy convencido de que gane nada de esto. Si resulta útil, intentaré llevarlo al resto de mi equipo.
Mi pregunta principal es esta: ¿serviría TDD para algún propósito del código, si ya puedo probar la corrección del código?
Obviamente, ninguno de los dos es una bala de plata. Su prueba puede estar equivocada porque omitió un detalle, y su prueba podría fallar al detectar un error que no pudo probar. Al final, somos humanos, nadie puede hacer código 100% libre de errores para siempre. Solo podemos esforzarnos por acercarnos lo más posible.
Sin embargo, ¿TDD realmente ahorraría tiempo en código que tuviera su corrección probada? es decir, código que, en la máquina de estado en la que opera el código, todos los estados posibles válidos y sus rangos son reconocidos por el desarrollador, todos se tienen en cuenta y el código está diseñado en una verificación de errores de estilo de lista blanca que pasa todas las excepciones a un controlador superior para asegurarse de que no haya fugas inesperadas -> sin mostrar un mensaje relevante (dentro de lo razonable) al cliente y sin enviar notificaciones de registro a un administrador.
Las respuestas con ejemplos de la vida real serían mejores.
Algunas aclaraciones:
Esta pregunta no se trata de si puede probar la corrección del código o no. Asumamos por defecto que no todo el código puede probarse correcto dentro de un plazo razonable, pero que algunos fragmentos de código pueden serlo. Por ejemplo, es muy fácil comprobar la corrección de un módulo FizzBuzz. No es muy fácil para un servicio de sincronización de datos basado en la nube.
Dentro de este límite, la pregunta plantea lo siguiente: Comience con la suposición de que una base de código se divide en 2 partes: [I] partes que se han demostrado correctas [II] partes que no se han demostrado correctas, pero que se probaron manualmente para que funcionen.
Quiero aplicar prácticas TDD a esta base de código que no las tenía hasta ahora. La pregunta es la siguiente: ¿se debe aplicar TDD a cada módulo o sería suficiente aplicarlos solo a los módulos que no se probaron correctamente?
"Probado correcto" significa que puede considerar este módulo con un estilo completamente funcional, es decir, no se basa en ningún estado global o externo fuera de sí mismo, y tiene completamente su propia API para E / S que deben seguir otros módulos que interactúan con él. . No es posible "romper este módulo" cambiando el código fuera del módulo, en el peor de los casos, puede usarlo mal y recibir mensajes de error formateados.
Obviamente, cada regla tiene excepciones, los errores del compilador en las nuevas versiones del compilador pueden introducir errores en este módulo, pero podrían introducirse los mismos errores en las pruebas que lo probaron y dar como resultado una falsa sensación de seguridad de las pruebas que ya no funcionan según lo previsto. La conclusión es que las pruebas no son una solución mágica, son otra capa de protección, y esta pregunta discute el tema de si esta capa de protección vale la pena en el caso específico de un módulo que se demostró que es correcto (suponga que era de hecho).
Respuestas:
Si.
Las pruebas están bien cuando están disponibles, pero incluso en el mejor de los casos, solo prueban que un solo bit de código funcionará como se esperaba (para todas las entradas, que representan interrupciones en el medio de cualquier operación), ¿qué hay de quedarse sin memoria? ? falla de disco? falla de red?).
¿Qué pasa cuando cambia?
Las pruebas son excelentes porque sirven como un contrato implícito sobre lo que debe hacer el código. Proporcionan algunos andamios para que su nuevo pasante pueda entrar y hacer cambios con cierto nivel de confianza. Todo a través de resultados rápidos y claros: pasar o fallar.
Y, francamente, puedo entrenar a un pasante para escribir pruebas unitarias viables en unos pocos meses. Dudo que alguien en mi equipo (incluido yo mismo) pueda crear pruebas que garanticen algo significativo para un código no trivial; y mucho menos hacerlo de forma rápida y precisa.
fuente
For large & rapidly changing projects
cuanto más propensos a cambiar, más necesarias son las pruebas, ya que un código cambiante tiene muchas más posibilidades de fallar debido a nuevos errores o comportamientos inesperados, que el código que apenas cambia. Es una cuestión de probabilidad. Incluso si no cambia a menudo, después de un tiempo el conocimiento obtenido durante el desarrollo podría perderse o caer en el olvido. Las pruebas también son conocimientos materializados, que pueden reducir, significativamente, la curva de aprendizaje. ¿Las pruebas de codificación requieren mucho tiempo? Si. ¿Hace más caro el proyecto? No, a la larga lo hace más barato .No lo sabemos No podemos responder tu pregunta.
Si bien pasa mucho tiempo explicando que el proceso que tiene ahora parece funcionar para satisfacción de todos, nos está contando solo una pequeña parte de lo que realmente está sucediendo.
Según mi experiencia, lo que está describiendo es una rareza extrema y soy escéptico de que sea realmente su proceso y enfoque de codificación lo que en realidad sea la causa del bajo recuento de errores en sus aplicaciones. Puede haber muchos otros factores que influyen en sus aplicaciones y no nos dice nada sobre esos factores.
Por lo tanto, no sabemos, frente a no conocer su entorno y cultura de desarrollo exactos, si TDD lo ayudará o no. Y podemos pasar días discutiendo y discutiendo al respecto.
Solo podemos darte una recomendación: pruébalo. Experimentar. Aprenderlo. Sé que estás tratando de gastar la menor cantidad de esfuerzo para decidir, pero eso no es posible. Si realmente desea saber si TDD funcionará en su contexto, la única forma de averiguarlo es hacer TDD. Si realmente lo aprende y lo aplica a su solicitud, puede compararlo con su proceso que no es TDD. Puede ser que TDD realmente tenga ventajas y usted decida conservarlo. O puede resultar que TDD no trae nada nuevo y solo te ralentiza. En cuyo caso, puede recurrir a su proceso anterior.
fuente
El propósito principal de las pruebas (unitarias) es salvaguardar el código, asegurándose de que no pase desapercibido debido a cambios posteriores. Cuando se escribe el código por primera vez, recibirá mucha atención y se examinará. Y es posible que tenga un sistema superior para eso.
Seis meses después, cuando alguien más está trabajando en algo que aparentemente no está relacionado, puede romperse y su superduper probador de corrección de código no lo notará. Una prueba automática lo hará.
fuente
Esta es la forma más difícil de aprender TDD. Cuanto más tarde realice la prueba, más le costará escribir las pruebas y menos obtendrá de escribirlas.
No digo que sea imposible adaptar las pruebas a una base de código existente. Estoy diciendo que es probable que hacerlo no convierta a nadie en un creyente TDD. Este es un trabajo duro.
En realidad, es mejor practicar TDD la primera vez en algo nuevo y en casa. De esa manera aprendes el ritmo real. Haga esto bien y lo encontrará adictivo.
Eso es pensamiento estructural. No debe decir cosas como probar cada función, clase o módulo. Esos límites no son importantes para las pruebas y deberían poder cambiar de todos modos. TDD se trata de establecer una necesidad de comportamiento comprobable y no preocuparse de cómo se satisface. Si no fuera así, no podríamos refactorizar.
Es suficiente aplicarlos donde los necesite. Empezaría con un nuevo código. Obtendrá mucho más de vuelta de la prueba temprana que tarde. No hagas esto en el trabajo hasta que hayas practicado lo suficiente como para dominarlo en casa.
Cuando haya demostrado que TDD es eficaz con el nuevo código en el trabajo y se siente lo suficientemente seguro como para asumir el código anterior, comenzaría con el código probado. La razón es porque podrás ver de inmediato si las pruebas que estás escribiendo están llevando el código en una buena dirección.
Las pruebas no solo prueban la corrección. Muestran intención. Muestran lo que se necesita. Señalan un camino hacia el cambio. Una buena prueba dice que hay varias formas de escribir este código y obtener lo que desea. Ayudan a los nuevos programadores a ver lo que pueden hacer sin romper todo.
Solo una vez que tenga eso abajo, debe deambular por el código no probado.
Una advertencia contra los fanáticos: parece que has logrado el éxito y, por lo tanto, es poco probable que saltes de cabeza. Pero otros que buscan probarse a sí mismos no serán tan reservados. TDD puede ser exagerado. Es increíblemente fácil crear un conjunto de pruebas que realmente perjudica la refactorización porque bloquean cosas triviales y sin sentido. ¿Como sucedió esto? Porque las personas que buscan mostrar pruebas simplemente escriben pruebas y nunca refactorizan. ¿Solución? Hazlos refactorizar. Haz que se ocupen de los cambios de funciones. Cuanto antes mejor. Eso te mostrará las pruebas inútiles rápidamente. Usted demuestra flexibilidad flexionando.
Una advertencia contra la categorización estructural: algunas personas insistirán en que una clase es una unidad. Algunos llamarán a cualquier prueba con dos clases una prueba de integración. Algunos insistirán en que no puedes cruzar el límite x y lo llamarán una prueba unitaria. En lugar de preocuparse por nada de eso, le aconsejo que se preocupe por cómo se comporta su prueba. ¿Se puede ejecutar en una fracción de segundo? ¿Se puede ejecutar en paralelo con otras pruebas (sin efectos secundarios)? ¿Se puede ejecutar sin iniciar o editar otras cosas para satisfacer dependencias y condiciones previas? Puse estas consideraciones por delante si habla con una base de datos, sistema de archivos o red. ¿Por qué? Porque estos tres últimos son solo problemas porque causan los otros problemas. Agrupe sus pruebas en función de cómo puede esperar que se comporten. No los límites que pasan para cruzar. Entonces sabrá lo que puede esperar que haga cada conjunto de pruebas.
Esa pregunta ya tiene respuestas aquí .
fuente
Test Driven Development tiene más que ver con la creación de prototipos y la lluvia de ideas de una API que con las pruebas. Las pruebas creadas son a menudo de baja calidad y eventualmente tienen que descartarse. La principal ventaja de TDD es determinar cómo se utilizará una API, antes de escribir la implementación de la API. Esta ventaja también se puede obtener de otras maneras, por ejemplo, escribiendo documentación de API antes de la implementación.
Las pruebas de corrección son siempre más valiosas que las pruebas. Las pruebas no prueban nada. Sin embargo, para utilizar las pruebas de corrección de manera productiva, es útil contar con un verificador de pruebas automatizado, y deberá trabajar utilizando contratos de algún tipo (diseño por contrato o diseño basado en contrato).
En el pasado, cuando trabajaba en secciones críticas de código, intentaba pruebas de corrección manual. Incluso las pruebas informales son más valiosas que cualquier prueba automatizada. Pero aún necesita las pruebas, a menos que pueda automatizar sus pruebas, ya que las personas romperán su código en el futuro.
Las pruebas automatizadas no implican TDD.
fuente
String getSomeValue()
aquí para que podamos probarlo" cuando eso no tiene sentido para el diseño general. Claro, podría eliminar esa función más tarde, pero, en mi experiencia, eso es raro.A) Al leer el código y convencerse de que es correcto, no está ni remotamente cerca de demostrar que es correcto. De lo contrario, ¿por qué escribir pruebas?
B) Cuando cambie el código, desea ejecutar pruebas que demuestren que el código sigue siendo correcto o no.
fuente
Voy a advertir que una vez que esté acostumbrado a usar TDD de manera efectiva, le ahorrará tiempo al final del juego. Se necesita práctica para aprender a usar TDD de manera efectiva, y no ayuda cuando estás en una crisis de tiempo. Cuando aprenda a utilizarlo mejor, le recomiendo comenzar un proyecto personal en el que tenga más margen de maniobra y menos presión en el horario.
Verás que tu progreso inicial es más lento mientras experimentas más y escribes tu API. Con el tiempo, su progreso será más rápido a medida que sus nuevas pruebas comiencen a pasar sin cambiar el código, y tenga una base muy estable para construir. En el juego tardío, el código que no se construye con TDD requiere que pases mucho más tiempo en el depurador mientras tratas de descubrir qué está yendo mal de lo que debería ser necesario. También corre mayor riesgo de romper algo que solía funcionar con nuevos cambios. Evaluar la efectividad de TDD versus no usarlo por el tiempo total hasta su finalización.
Dicho esto, TDD no es el único juego en la ciudad. Puede usar BDD, que usa una forma estándar de expresar el comportamiento de una aplicación de pila completa, y evaluar la corrección de la API desde allí.
Todo su argumento depende de "probar la corrección del código", por lo que necesita algo que defina la corrección del código. Si no está utilizando una herramienta automatizada para definir qué significa "correcto", entonces la definición es muy subjetiva. Si su definición de correcto se basa en el consenso de sus pares, eso puede cambiar en un día determinado. Su definición de correcto debe ser concreta y verificable, lo que también significa que debe poder ser evaluada por una herramienta. ¿Por qué no usar uno?
La victoria número 1 al usar pruebas automáticas de cualquier tipo es que puede verificar que su código siga siendo correcto incluso cuando los parches del sistema operativo se aplican de manera rápida y eficiente. Ejecute su suite para asegurarse de que todo esté pasando, luego aplique el parche y vuelva a ejecutar la suite. Aún mejor, hágalo parte de su infraestructura de construcción automatizada. Ahora puede verificar que su código siga siendo correcto después de fusionar el código de varios desarrolladores.
Mi experiencia con TDD me ha llevado a las siguientes conclusiones:
Mi experiencia con BDD me ha llevado a las siguientes conclusiones:
Definición de correcto: su código cumple con los requisitos. Esto se verifica mejor con BDD, que proporciona un medio para expresar esos requisitos de una manera legible para los humanos y verificarlos en tiempo de ejecución.
No estoy hablando de la corrección en términos de pruebas matemáticas, lo cual no es posible. Y estoy cansado de tener esa discusión.
fuente