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.
Como su nombre indica, está probando un sujeto atómico en cada prueba. Tal tema suele ser un método único. Múltiples pruebas pueden probar el mismo método, para cubrir el camino feliz, posibles errores, etc. Está probando el comportamiento, no la mecánica interna. Por lo tanto, las pruebas unitarias se tratan realmente de probar la interfaz pública de una clase, es decir, un método específico.
En las pruebas unitarias, un método debe probarse de forma aislada, es decir, tropezando / burlándose / falsificando cualquier dependencia. De lo contrario, probar una unidad con dependencias 'reales' la convierte en una prueba de integración. Hay un momento y lugar para ambos tipos de pruebas. Las pruebas unitarias aseguran que un solo sujeto funcione como se esperaba, independiente. Las pruebas de integración aseguran que los sujetos 'reales' trabajen juntos correctamente.
fuente
Mi regla de oro: la unidad de código más pequeña que sigue siendo lo suficientemente compleja como para contener errores.
Si este es un método o clase o subsistema depende del código particular, no se puede dar una regla general.
Por ejemplo, no proporciona ningún valor para probar métodos getter / setter simples de forma aislada, o métodos wrapper que solo llaman a otro método. Incluso una clase completa puede ser demasiado simple para probar, si la clase es solo un envoltorio o adaptador delgado. Si lo único que se debe probar es si se llama a un método simulado, entonces el código que se está probando es delgado.
En otros casos, un solo método puede realizar algunos cálculos complejos que son valiosos para probar de forma aislada.
En muchos casos, las partes complejas no son clases individuales sino más bien la integración entre clases. Entonces prueba dos o más clases a la vez. Algunos dirán que esto no son pruebas unitarias sino pruebas de integración, pero no importa la terminología: debe probar dónde está la complejidad, y estas pruebas deberían ser parte del conjunto de pruebas.
fuente