Acabo de comprar The Art of Unit Testing de Amazon. Soy bastante serio sobre la comprensión de TDD, así que puede estar seguro de que esta es una pregunta genuina.Intentando ganar confianza en los beneficios de TDD
Pero siento que estoy constantemente a punto de encontrar la justificación para renunciar a ella.
Voy a jugar al abogado del diablo aquí y tratar de derribar los supuestos beneficios de TDD con la esperanza de que alguien pueda demostrar que estoy equivocado y ayudarme a tener más confianza en sus virtudes. Creo que me estoy perdiendo algo, pero no puedo entender qué.
1. TDD para reducir errores
Este often-cited blog post dice que las pruebas unitarias son herramientas de diseño y no para la captura de insectos:
En mi experiencia, las pruebas de unidad no son una manera eficaz de encuentra errores o detecta regresiones.
...
TDD es una forma sólida de diseñar componentes de software (“unidades”) forma interactiva por lo que su comportamiento se especifica a través de pruebas de unidad. ¡Eso es todo!
Tiene sentido. Los casos extremos siempre van a estar ahí, y solo encontrarás los errores superficiales, que son los que encontrarás tan pronto como ejecutes tu aplicación de todos modos. Aún debe realizar pruebas de integración adecuadas después de que haya terminado de construir una buena parte de su software.
Lo suficiente, la reducción de errores no es lo único que se supone que TDD ayuda.
2. TDD como un paradigma de diseño
Este es probablemente el más grande. TDD es un paradigma de diseño que lo ayuda (o le obliga) a hacer que su código sea más composable.
Pero la capacidad de compilación es una calidad de realización múltiple; el estilo de programación funcional, por ejemplo, hace que el código sea también composable. Por supuesto, es difícil escribir una aplicación a gran escala completamente en estilo funcional, pero existen ciertos patrones de compromiso que puede seguir para mantener la capacidad de compilación.
Si comienza con un diseño funcional altamente modular, y luego agrega cuidadosamente el estado y IO a su código según sea necesario, terminará con los mismos patrones que TDD alienta. Por ejemplo, para ejecutar la lógica de negocios en una base de datos, el código IO podría aislarse en una función que realiza las tareas "monádicas" de acceder a la base de datos y pasarlo como argumento a la función responsable de la lógica comercial . Esa sería la forma funcional de hacerlo.
Por supuesto, esto es un poco torpe, por lo tanto, en su lugar, podríamos arrojar un subconjunto del código IO de la base de datos en una clase y darlo a un objeto que contenga la lógica empresarial relevante. Es exactamente lo mismo, una adaptación de la forma funcional de hacer las cosas, y se conoce como el patrón de repositorio.
Sé que esto probablemente me gane una flagelación bastante mala, pero muchas veces, no puedo evitar sentir que TDD solo compensa algunos de los malos hábitos que la POO puede alentar, los que pueden ser evitado con un poco de inspiración del estilo funcional.
3. TDD como documentación
TDD se dice que sirven como documentación, pero sólo sirve como documentación para sus compañeros; el consumidor aún requiere documentación de texto.
Por supuesto, un método TDD podría servir como base para código de muestra, pero las pruebas generalmente contienen algún grado de simulaciones que no deberían estar en el código de muestra, y suelen ser bastante ingeniosas para que puedan evaluarse contra el resultado esperado.
Una buena prueba de unidad describirá en su método la firma del comportamiento exacto que se está verificando, y la prueba no verificará más ni menos que ese comportamiento.
Por lo tanto, yo diría que es mejor dedicar su tiempo a pulir su documentación. Diablos, ¿por qué no hacer solo la documentación primero y llamarlo Diseño orientado a la documentación?
4. TDD para pruebas de regresión
Es mencionado en ese puesto por encima de ese TDD no es demasiado útil para detectar regresiones. Eso es, por supuesto, porque los casos extremos no obvios son los que siempre se estropean cuando cambias algún código.
Lo que también podría tenerse en cuenta sobre ese tema es que hay muchas posibilidades de que más de su código permanezca igual durante bastante tiempo. Entonces, ¿no tendría más sentido escribir pruebas unitarias según sea necesario, siempre que se cambie el código, manteniendo el código anterior y comparando sus resultados con los de la nueva función?
"que se pueden evitar con un poco de inspiración del estilo funcional". Casi estoy de acuerdo ... TDD fomenta un estilo de codificación más cercano al modelo Actor, que es una especie de inversión del estilo funcional (es un modelo push en comparación con el tirón de la codificación funcional) – kyoryu
Interesante ... Debería ver el modelo Actor . ¡Eso podría contener la respuesta que estoy buscando! –
Vale la pena señalar que Alan Kay ha sido citado diciendo que lamenta utilizar el término "orientado a objetos" y desearía haber usado "orientado a mensajes". TDD lo empuja hacia un estilo orientado a mensajes (que es el corazón del modelo actor, o la comunicación de procesos secuenciales, o ...) – kyoryu