Originalmente, TDD provenía del movimiento ágil, donde las pruebas se escribieron por adelantado como una forma de garantizar que lo que codificó se mantuvo correcto dada la especificación que ahora estaba bien definida en el código de prueba. También apareció como un aspecto muy importante de la refactorización, ya que cuando modificaba su código, podía confiar en las pruebas para demostrar que no había cambiado el comportamiento del código.
Luego, las personas llegaron y pensaron que sabían información sobre su código y luego pudieron generar comprobantes de prueba para ayudarlo a escribir sus pruebas unitarias, y creo que aquí es donde todo salió mal.
Los resguardos de prueba son generados por una computadora que no tiene idea de lo que está haciendo, simplemente produce un resguardo para cada método porque eso es lo que se le dice que haga. Esto significa que tiene un caso de prueba para cada método, independientemente de la complejidad de ese método o si es adecuado para realizar pruebas de forma aislada.
Esto viene en las pruebas desde el lado equivocado de la metodología TDD. En TDD, se supone que debe averiguar qué debe hacer el código y luego generar un código que lo logre. Esto es autocumplido, ya que terminas escribiendo pruebas que prueban que el código hace lo que hace, no lo que se supone que debe hacer. En combinación con la generación automática de comprobantes de prueba basados en métodos, prácticamente pierdes tu tiempo probando cada pequeño aspecto de tu código que fácilmente puede resultar incorrecto cuando se juntan todas las piezas pequeñas.
Cuando Fowler describió las pruebas en su libro, se refirió a probar cada clase con su propio método principal. Él mejoró esto, pero el concepto sigue siendo el mismo: se prueba toda la clase para que funcione como un todo, todas sus pruebas se agrupan para probar la interacción de todos esos métodos para que la clase se pueda reutilizar con expectativas definidas.
Creo que los kits de herramientas de prueba nos han perjudicado, nos llevaron a pensar que el kit de herramientas es la única forma de hacer las cosas cuando realmente necesita pensar más para obtener el mejor resultado de su código. Poner a ciegas el código de prueba en trozos de prueba para piezas pequeñas solo significa que tienes que repetir tu trabajo en una prueba de integración de todos modos (y si vas a hacer eso, ¿por qué no omitir la etapa de prueba de unidad ahora redundante por completo). También significa que las personas pierden mucho tiempo tratando de obtener una cobertura de prueba del 100%, y mucho tiempo creando grandes cantidades de código de burla y datos que se habrían gastado mejor haciendo que el código sea más fácil para la prueba de integración (es decir, si tiene tanto dependencias de datos, la prueba unitaria podría no ser la mejor opción)
Por último, la fragilidad de las pruebas unitarias basadas en métodos simplemente muestra el problema. La refactorización está diseñada para usarse con pruebas unitarias, si sus pruebas se rompen todo el tiempo porque está refactorizando, entonces algo ha salido muy mal con todo el enfoque. Refactorizar le gusta crear y eliminar métodos, por lo que, obviamente, el enfoque de prueba ciego por método no es lo que se pretendía originalmente.
No tengo dudas de que muchos métodos obtendrán pruebas escritas para ellos, todos los métodos públicos de una clase deben ser probados, pero no puede alejarse del concepto de probarlos juntos como parte de un solo caso de prueba. Por ejemplo, si tengo un conjunto y un método get, puedo escribir pruebas que coloquen los datos y verificar que los miembros internos estén configurados correctamente, o puedo usar cada uno para poner algunos datos y luego sacarlos nuevamente para ver si son sigue siendo el mismo y no está distorsionado. Esto prueba la clase, no cada método de forma aislada. Si el setter se basa en un método privado auxiliar, entonces está bien: no necesita burlarse del método privado para asegurarse de que el setter esté funcionando, no si prueba toda la clase.
Creo que la religión se está metiendo en este tema, por lo tanto, se ve el cisma en lo que ahora se conoce como desarrollo 'impulsado por el comportamiento' y 'impulsado por la prueba': el concepto original de pruebas unitarias era para el desarrollo impulsado por el comportamiento.