Probar el código en general no es fácil. Si así fuera, lo hubiéramos estado haciendo hace mucho tiempo, y no hubiéramos hecho tan poco en los últimos 10-15 años. Una de las mayores dificultades siempre ha sido determinar cómo probar el código que se ha escrito de manera coherente, bien factorizado y comprobable sin romper la encapsulación. El director de BDD sugiere que nos centremos casi por completo en el comportamiento, y de alguna manera parece sugerir que realmente no necesita preocuparse por los detalles internos en un grado tan grande, pero esto a menudo puede hacer que las cosas sean bastante difíciles de probar si hay una gran cantidad de métodos privados que hacen "cosas" de una manera muy oculta, ya que puede aumentar la complejidad general de su prueba para tratar todos los resultados posibles a un nivel más público.
La burla puede ayudar hasta cierto punto, pero de nuevo está bastante centrada externamente. La inyección de dependencia también puede funcionar bastante bien, de nuevo con simulacros o dobles de prueba, pero esto también puede requerir que exponga elementos, ya sea a través de una interfaz o directamente, que de lo contrario hubiera preferido permanecer oculto; esto es particularmente cierto si desea tener un buen nivel de seguridad paranoico sobre ciertas clases dentro de su sistema.
Para mí, el jurado aún no sabe si diseñar sus clases para que sean más fácilmente comprobables. Esto puede crear problemas si necesita proporcionar nuevas pruebas mientras mantiene el código heredado. Acepto que deberías poder probar absolutamente todo en un sistema, pero no me gusta la idea de exponer, incluso indirectamente, los elementos internos privados de una clase, solo para poder escribir una prueba para ellos.
Para mí, la solución siempre ha sido adoptar un enfoque bastante pragmático y combinar una serie de técnicas para adaptarse a cada situación específica. Utilizo muchos dobles de prueba heredados para exponer propiedades y comportamientos internos para mis pruebas. Me burlo de todo lo que se puede adjuntar a mis clases, y donde no comprometa la seguridad de mis clases, proporcionaré un medio para anular o inyectar comportamientos con el propósito de probar. Incluso consideraré proporcionar una interfaz más controlada por eventos si ayuda a mejorar la capacidad de probar el código
Cuando encuentro un código "no comprobable" , veo si puedo refactorizar para hacer las cosas más comprobables. Cuando tienes un montón de código privado oculto detrás de escena, a menudo encontrarás nuevas clases a la espera de ser divididas. Estas clases se pueden usar internamente, pero a menudo se pueden probar de forma independiente con comportamientos menos privados y, a menudo, con menos capas de acceso y complejidad. Sin embargo, una cosa que debo evitar es escribir el código de producción con el código de prueba incorporado. Puede ser tentador crear " lengüetas de prueba " que resulten en la inclusión de horrores como if testing then ...
, lo que indica un problema de prueba que no está completamente deconstruido y resuelto de manera incompleta.
Puede que le resulte útil leer el libro de Patrones de prueba xUnit de Gerard Meszaros , que cubre todo este tipo de cosas con mucho más detalle de lo que puedo analizar aquí. Probablemente no hago todo lo que él sugiere, pero ayuda a aclarar algunas de las situaciones de prueba más difíciles de manejar. Al final del día, desea poder satisfacer sus requisitos de prueba mientras sigue aplicando sus diseños preferidos, y ayuda a comprender mejor todas las opciones para poder decidir mejor dónde podría comprometer.